ES2 Support?

This commit is contained in:
TheBrokenRail 2023-09-07 21:17:21 -04:00
parent 3078b26756
commit 21f52cba33
13 changed files with 290 additions and 4 deletions

View File

@ -11,10 +11,20 @@ if(GLES_COMPATIBILITY_LAYER_USE_DEFAULT_INCLUDE_PATH)
target_include_directories(gles-compatibility-layer PUBLIC include)
endif()
# GL Version
option(GLES_COMPATIBILITY_LAYER_USE_ES3 "Use OpenGL ES 3" TRUE)
if(GLES_COMPATIBILITY_LAYER_USE_ES3)
target_compile_definitions(gles-compatibility-layer PUBLIC GLES_COMPATIBILITY_LAYER_USE_ES3)
endif()
# Shaders
include(cmake/util.cmake)
embed_resource(gles-compatibility-layer src/shaders/main.vsh)
embed_resource(gles-compatibility-layer src/shaders/main.fsh)
set(SHADER_FOLDER "es2")
if(GLES_COMPATIBILITY_LAYER_USE_ES3)
set(SHADER_FOLDER "es3")
endif()
embed_resource(gles-compatibility-layer "src/shaders/${SHADER_FOLDER}/main.vsh")
embed_resource(gles-compatibility-layer "src/shaders/${SHADER_FOLDER}/main.fsh")
# Warnings
target_compile_options(gles-compatibility-layer PRIVATE -Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 TheBrokenRail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -170,6 +170,7 @@ void glLightModelfv(GLenum pname, const GLfloat *params);
void glPixelStorei(GLenum pname, GLint param);
// Not Part Of OpenGL ES 1.1
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
#define GL_SAMPLES_PASSED_ARB 0x8c2f // GL_ANY_SAMPLES_PASSED
#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 // GL_QUERY_RESULT_AVAILABLE
#define GL_QUERY_RESULT_ARB 0x8866 // GL_QUERY_RESULT
@ -178,6 +179,7 @@ void glDeleteQueriesARB(GLsizei n, const GLuint *ids);
void glBeginQueryARB(GLenum target, GLuint id);
void glEndQueryARB(GLenum target);
void glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params);
#endif
void extra_enable_highlight_mode(float red, float green, float blue, float alpha);
void extra_disable_highlight_mode();

View File

@ -115,9 +115,10 @@ static GLuint get_shader() {
}
// Init
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays));
GL_FUNC(glBindVertexArray, void, (GLuint array));
GL_FUNC(glActiveTexture, void, (GLenum texture));
#endif
void init_gles_compatibility_layer() {
// State
_init_gles_compatibility_layer_state();
@ -126,9 +127,11 @@ void init_gles_compatibility_layer() {
reset_variables();
// Setup VAO
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
GLuint vao;
real_glGenVertexArrays()(1, &vao);
real_glBindVertexArray()(vao);
#endif
// Load Shader
GLuint program = get_shader();

View File

@ -120,6 +120,7 @@ GL_FUNC(glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size,
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
real_glBufferSubData()(target, offset, size, data);
}
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
GL_FUNC(glGenQueries, void, (GLsizei n, GLuint *ids));
void glGenQueriesARB(GLsizei n, GLuint *ids) {
real_glGenQueries()(n, ids);
@ -140,6 +141,7 @@ GL_FUNC(glGetQueryObjectuiv, void, (GLuint id, GLenum pname, GLuint *params));
void glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) {
real_glGetQueryObjectuiv()(id, pname, params);
}
#endif
GL_FUNC(glPixelStorei, void, (GLenum pname, GLint param));
void glPixelStorei(GLenum pname, GLint param) {
real_glPixelStorei()(pname, param);

View File

@ -8,6 +8,18 @@
#include "log.h"
// Testing
#ifdef GLES_COMPATIBILITY_LAYER_TESTING
typedef void (*test_t)();
extern void add_test(const char *function_name);
#define ADD_TEST(test) \
__attribute__((constructor)) static void add_##test##_test() { \
add_test(#test); \
}
#else
#define ADD_TEST(test)
#endif
// Load GL Function
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
#define GL_APIENTRY __stdcall
@ -26,4 +38,5 @@
} \
} \
return func; \
}
} \
ADD_TEST(name)

50
src/shaders/es2/main.fsh Normal file
View File

@ -0,0 +1,50 @@
#version 100
precision highp float;
// Texture
uniform bool u_has_texture;
uniform sampler2D u_texture_unit;
// Color
varying vec4 v_color;
varying vec4 v_texture_pos;
// Highlight Mode
uniform bool u_highlight_mode;
uniform vec4 u_highlight_mode_color;
// Alpha Test
uniform bool u_alpha_test;
// Fog
uniform bool u_fog;
uniform vec4 u_fog_color;
uniform bool u_fog_is_linear;
uniform float u_fog_start;
uniform float u_fog_end;
varying vec4 v_fog_eye_position;
// Main
void main(void) {
gl_FragColor = v_color;
// Texture
if (u_has_texture) {
vec4 texture_color = texture(u_texture_unit, v_texture_pos.xy);
if (u_highlight_mode) {
texture_color.rgb = u_highlight_mode_color.rgb;
texture_color.a *= u_highlight_mode_color.a;
gl_FragColor = texture_color;
} else {
gl_FragColor *= texture_color;
}
}
// Fog
if (u_fog) {
float fog_factor;
if (u_fog_is_linear) {
fog_factor = (u_fog_end - length(v_fog_eye_position)) / (u_fog_end - u_fog_start);
} else {
fog_factor = exp(-u_fog_start * length(v_fog_eye_position));
}
fog_factor = clamp(fog_factor, 0.0, 1.0);
gl_FragColor.rgb = mix(gl_FragColor, u_fog_color, 1.0 - fog_factor).rgb;
}
// Alpha Test
if (u_alpha_test && gl_FragColor.a <= 0.1) {
discard;
}
}

48
src/shaders/es2/main.vsh Normal file
View File

@ -0,0 +1,48 @@
#version 100
precision highp float;
// Matrices
uniform mat4 u_projection;
uniform mat4 u_model_view;
uniform mat4 u_texture;
// Texture
attribute vec3 a_vertex_coords;
attribute vec2 a_texture_coords;
varying vec4 v_texture_pos;
// Color
attribute vec4 a_color;
varying vec4 v_color;
// Normal
attribute vec3 a_normal;
uniform float u_normal_rescale_factor;
// Lighting
uniform bool u_lighting;
uniform vec4 u_lighting_ambient;
uniform bool u_lighting_light_source_0;
uniform vec3 u_lighting_light_source_0_position;
uniform vec4 u_lighting_light_source_0_diffuse;
uniform bool u_lighting_light_source_1;
uniform vec3 u_lighting_light_source_1_position;
uniform vec4 u_lighting_light_source_1_diffuse;
// Fog
varying vec4 v_fog_eye_position;
// Main
void main(void) {
v_texture_pos = u_texture * vec4(a_texture_coords.xy, 0.0, 1.0);
gl_Position = u_projection * u_model_view * vec4(a_vertex_coords.xyz, 1.0);
v_color = a_color;
v_fog_eye_position = u_model_view * vec4(a_vertex_coords.xyz, 1.0);
// Lighting
if (u_lighting) {
vec4 transformed_normal = u_model_view * vec4(a_normal, 0.0) * u_normal_rescale_factor;
vec4 total_light = u_lighting_ambient;
if (u_lighting_light_source_0) {
total_light += max(0.0, dot(transformed_normal.xyz, u_lighting_light_source_0_position)) * u_lighting_light_source_0_diffuse;
}
if (u_lighting_light_source_1) {
total_light += max(0.0, dot(transformed_normal.xyz, u_lighting_light_source_1_position)) * u_lighting_light_source_1_diffuse;
}
total_light = clamp(total_light, 0.0, 1.0);
v_color *= total_light;
}
}

1
test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

11
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.16.0)
project(gles-compatibility-layer-test)
# Build Library
set(GLES_COMPATIBILITY_LAYER_USE_SDL FALSE CACHE BOOL "" FORCE)
add_subdirectory(.. gles-compatibility-layer)
target_compile_definitions(gles-compatibility-layer PRIVATE GLES_COMPATIBILITY_LAYER_TESTING)
# Build
add_executable(main src/main.cpp)
target_link_libraries(main gles-compatibility-layer)

125
test/src/main.cpp Normal file
View File

@ -0,0 +1,125 @@
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <fstream>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <GLES/gl.h>
#define INFO(format, ...) \
{ \
fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__); \
}
#define WARN(format, ...) \
{ \
fprintf(stderr, "[WARN]: " format "\n", ##__VA_ARGS__); \
}
#define ERR(format, ...) \
{ \
fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
exit(EXIT_FAILURE); \
}
// Tests
#define MAX_TESTS 255
static const char *tests[MAX_TESTS] = { 0 };
extern "C" void add_test(const char *function_name) {
static int i = 0;
if (i >= MAX_TESTS) {
ERR("Too Many Tests!");
}
tests[i++] = function_name;
}
// Header Files
static std::vector<std::string> header_lines;
static void load_header(std::string filename) {
std::ifstream file(filename);
if (!file.good()) {
ERR("Unable To Load Header: %s", filename.c_str());
}
std::string line;
while (std::getline(file, line)) {
header_lines.push_back(line);
}
file.close();
}
static void load_headers() {
header_lines.clear();
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
load_header("/usr/include/GLES3/gl3.h");
#else
load_header("/usr/include/GLES2/gl2.h");
#endif
}
// Run Test
static void run_test(std::string function_name) {
// Log
INFO("Checking %s...", function_name.c_str());
// Search Headers
std::string check_str = " " + function_name + " ";
bool found = false;
for (std::string line : header_lines) {
if (line.find(check_str) != std::string::npos) {
// Found
found = true;
break;
}
}
if (!found) {
ERR("Unable To Find Function");
}
}
// Handle GLFW Error
static void glfw_error(__attribute__((unused)) int error, const char *description) {
WARN("GLFW Error: %s", description);
}
int main() {
INFO("Starting Test");
// Init GLFW
glfwSetErrorCallback(glfw_error);
if (!glfwInit()) {
ERR("Unable To Initialize GLFW");
}
// Create OpenGL ES Context
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#ifdef GLES_COMPATIBILITY_LAYER_USE_ES3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
#endif
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
// Create Window
GLFWwindow *glfw_window = glfwCreateWindow(640, 480, "Test Window", NULL, NULL);
if (!glfw_window) {
ERR("Unable To Create GLFW Window");
}
// Make Window Context Current
glfwMakeContextCurrent(glfw_window);
// Setup Compatibility Layer
init_gles_compatibility_layer();
// Run Tests
load_headers();
for (int i = 0; tests[i] != NULL; i++) {
run_test(tests[i]);
}
// Exit
glfwDestroyWindow(glfw_window);
glfwTerminate();
INFO("Test Complete");
}