Initial Commit
This commit is contained in:
commit
3dcbd2e903
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
project(gles-compatibility-layer)
|
||||
|
||||
# Build
|
||||
add_library(gles-compatibility-layer STATIC src/state.c src/passthrough.c src/matrix.c src/draw.c)
|
||||
target_link_libraries(gles-compatibility-layer m SDL)
|
||||
target_include_directories(gles-compatibility-layer PUBLIC include)
|
||||
# Shaders
|
||||
include(cmake/util.cmake)
|
||||
embed_resource(gles-compatibility-layer src/shaders/main.vsh)
|
||||
embed_resource(gles-compatibility-layer src/shaders/main.fsh)
|
||||
# Warnings
|
||||
target_compile_options(gles-compatibility-layer PRIVATE -Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
|
12
cmake/embed-resource.cmake
Normal file
12
cmake/embed-resource.cmake
Normal file
@ -0,0 +1,12 @@
|
||||
# Read Hex Data
|
||||
file(READ "${EMBED_IN}" data HEX)
|
||||
|
||||
# Convert Hex Data For C Compatibility
|
||||
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," data "${data}")
|
||||
|
||||
# Get C Name
|
||||
get_filename_component(name "${EMBED_IN}" NAME)
|
||||
string(MAKE_C_IDENTIFIER "${name}" name)
|
||||
|
||||
# Write Data
|
||||
file(WRITE "${EMBED_OUT}" "#include <stddef.h>\nconst unsigned char ${name}[] = {${data}};\nconst size_t ${name}_len = sizeof (${name});\n")
|
15
cmake/util.cmake
Normal file
15
cmake/util.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
# Embed Resources
|
||||
set(util_list_dir "${CMAKE_CURRENT_LIST_DIR}")
|
||||
function(embed_resource target file)
|
||||
# Get C Name
|
||||
get_filename_component(name "${file}" NAME)
|
||||
string(MAKE_C_IDENTIFIER "${name}" name)
|
||||
# Add Command
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
ARGS "-DEMBED_IN=${CMAKE_CURRENT_SOURCE_DIR}/${file}" "-DEMBED_OUT=${CMAKE_CURRENT_BINARY_DIR}/${name}.c" "-P" "${util_list_dir}/embed-resource.cmake"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "${util_list_dir}/embed-resource.cmake"
|
||||
)
|
||||
# Add To Target
|
||||
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
|
||||
endfunction()
|
188
include/GLES/gl.h
Normal file
188
include/GLES/gl.h
Normal file
@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GL_FALSE 0
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_MODELVIEW_MATRIX 0xba6
|
||||
#define GL_PROJECTION_MATRIX 0xba7
|
||||
#define GL_VIEWPORT 0xba2
|
||||
#define GL_DEPTH_TEST 0xb71
|
||||
#define GL_PACK_ALIGNMENT 0xd05
|
||||
#define GL_UNPACK_ALIGNMENT 0xcf5
|
||||
#define GL_SRC_ALPHA 0x302
|
||||
#define GL_DST_ALPHA 0x304
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x303
|
||||
#define GL_MODELVIEW 0x1700
|
||||
#define GL_PROJECTION 0x1701
|
||||
#define GL_TEXTURE 0x1702
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_COLOR_ARRAY 0x8076
|
||||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
#define GL_GREATER 0x204
|
||||
#define GL_ALPHA_TEST 0xbc0
|
||||
#define GL_TEXTURE_2D 0xde1
|
||||
#define GL_COLOR_MATERIAL 0xb57
|
||||
#define GL_PERSPECTIVE_CORRECTION_HINT 0xc50
|
||||
#define GL_FOG 0xb60
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_EXP 0x800
|
||||
#define GL_FOG_DENSITY 0xb62
|
||||
#define GL_FOG_START 0xb63
|
||||
#define GL_FOG_END 0xb64
|
||||
#define GL_FOG_MODE 0xb65
|
||||
#define GL_FOG_COLOR 0xb66
|
||||
#define GL_BLEND 0xbe2
|
||||
#define GL_TRIANGLES 0x4
|
||||
#define GL_TRIANGLE_STRIP 0x5
|
||||
#define GL_TRIANGLE_FAN 0x6
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_BACK 0x405
|
||||
#define GL_CULL_FACE 0xb44
|
||||
#define GL_LEQUAL 0x203
|
||||
#define GL_EQUAL 0x202
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x307
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x301
|
||||
#define GL_ZERO 0
|
||||
#define GL_FLAT 0x1d00
|
||||
#define GL_SMOOTH 0x1d01
|
||||
#define GL_SCISSOR_TEST 0xc11
|
||||
#define GL_TRUE 1
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SRC_COLOR 0x300
|
||||
#define GL_DST_COLOR 0x306
|
||||
#define GL_ONE 1
|
||||
#define GL_LINES 0x1
|
||||
#define GL_LINE_STRIP 0x3
|
||||
#define GL_STATIC_DRAW 0x88e4
|
||||
#define GL_DYNAMIC_DRAW 0x88e8
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812f
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
#define GL_DEPTH_BUFFER_BIT 0x100
|
||||
#define GL_COLOR_BUFFER_BIT 0x4000
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_NORMAL_ARRAY 0x8075
|
||||
#define GL_LIGHTING 0xb50
|
||||
#define GL_LIGHT0 0x4000
|
||||
#define GL_LIGHT1 0x4001
|
||||
#define GL_RESCALE_NORMAL 0x803a
|
||||
#define GL_AMBIENT 0x1200
|
||||
#define GL_DIFFUSE 0x1201
|
||||
#define GL_SPECULAR 0x1202
|
||||
#define GL_POSITION 0x1203
|
||||
#define GL_LIGHT_MODEL_AMBIENT 0xb53
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_ACCUM 0x100
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_NONE 0
|
||||
|
||||
typedef float GLfloat;
|
||||
typedef float GLclampf;
|
||||
typedef int GLint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned int GLuint;
|
||||
typedef ssize_t GLsizeiptr;
|
||||
typedef intptr_t GLintptr;
|
||||
typedef int32_t GLfixed;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef unsigned int GLenum;
|
||||
typedef char GLchar;
|
||||
typedef void GLvoid;
|
||||
|
||||
void glFogfv(GLenum pname, const GLfloat *params);
|
||||
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glLineWidth(GLfloat width);
|
||||
void glBlendFunc(GLenum sfactor, GLenum dfactor);
|
||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
void glClear(GLbitfield mask);
|
||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
void glFogx(GLenum pname, GLfixed param);
|
||||
#define glFogi glFogx
|
||||
void glFogf(GLenum pname, GLfloat param);
|
||||
void glMatrixMode(GLenum mode);
|
||||
void glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void glTexParameteri(GLenum target, GLenum pname, GLint param);
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
void glEnable(GLenum cap);
|
||||
void glEnableClientState(GLenum array);
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units);
|
||||
void glDisableClientState(GLenum array);
|
||||
void glDepthRangef(GLclampf near, GLclampf far);
|
||||
void glDepthFunc(GLenum func);
|
||||
void glBindBuffer(GLenum target, GLuint buffer);
|
||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
void glPopMatrix();
|
||||
void glLoadIdentity();
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void glPushMatrix();
|
||||
void glDepthMask(GLboolean flag);
|
||||
void glHint(GLenum target, GLenum mode);
|
||||
void glMultMatrixf(const GLfloat *m);
|
||||
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers);
|
||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
void glGenTextures(GLsizei n, GLuint *textures);
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures);
|
||||
void glAlphaFunc(GLenum func, GLclampf ref);
|
||||
void glGetFloatv(GLenum pname, GLfloat *params);
|
||||
void glBindTexture(GLenum target, GLuint texture);
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void glShadeModel(GLenum mode);
|
||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far);
|
||||
void glDisable(GLenum cap);
|
||||
void glCullFace(GLenum mode);
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
|
||||
GLboolean glIsEnabled(GLenum cap);
|
||||
void glGetIntegerv(GLenum pname, GLint *data);
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data);
|
||||
void glGenBuffers(GLsizei n, GLuint *buffers);
|
||||
GLenum glGetError();
|
||||
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
void glNormalPointer(GLenum type, GLsizei stride, const void *pointer);
|
||||
void glLightfv(GLenum light, GLenum pname, const GLfloat *params);
|
||||
void glLightModelfv(GLenum pname, const GLfloat *params);
|
||||
void glPixelStorei(GLenum pname, GLint param);
|
||||
|
||||
// Not Part Of OpenGL ES 1.1
|
||||
#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
|
||||
void glGenQueriesARB(GLsizei n, GLuint *ids);
|
||||
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);
|
||||
void extra_enable_highlight_mode(float red, float green, float blue, float alpha);
|
||||
void extra_disable_highlight_mode();
|
||||
|
||||
void init_gles_compatibility_layer();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
302
src/draw.c
Normal file
302
src/draw.c
Normal file
@ -0,0 +1,302 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "state.h"
|
||||
#include "passthrough.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
// Shaders
|
||||
#define REAL_GL_FRAGMENT_SHADER 0x8b30
|
||||
#define REAL_GL_VERTEX_SHADER 0x8b31
|
||||
#define REAL_GL_INFO_LOG_LENGTH 0x8b84
|
||||
#define REAL_GL_COMPILE_STATUS 0x8b81
|
||||
GL_FUNC(glUseProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetUniformLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glUniformMatrix4fv, void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
|
||||
GL_FUNC(glUniform1i, void, (GLint location, GLint v0));
|
||||
GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0));
|
||||
GL_FUNC(glUniform3f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2));
|
||||
GL_FUNC(glUniform4f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glGetAttribLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glEnableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glDisableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
|
||||
GL_FUNC(glVertexAttrib3f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2));
|
||||
GL_FUNC(glVertexAttrib4f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glCreateShader, GLuint, (GLenum type));
|
||||
GL_FUNC(glShaderSource, void, (GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC(glCompileShader, void, (GLuint shader));
|
||||
GL_FUNC(glCreateProgram, GLuint, ());
|
||||
GL_FUNC(glAttachShader, void, (GLuint program, GLuint shader));
|
||||
GL_FUNC(glLinkProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetShaderiv, void, (GLuint shader, GLenum pname, GLint *params));
|
||||
GL_FUNC(glGetShaderInfoLog, void, (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
|
||||
// Compile Shader
|
||||
static void log_shader(GLuint shader, const char *name) {
|
||||
// Log
|
||||
GLint log_length = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_INFO_LOG_LENGTH, &log_length);
|
||||
GLchar *log = malloc(log_length * sizeof (GLchar));
|
||||
ALLOC_CHECK(log);
|
||||
real_glGetShaderInfoLog()(shader, log_length, &log_length, log);
|
||||
if (log_length > 0) {
|
||||
if (log_length > 1 && log[log_length - 1] == '\n') {
|
||||
log[log_length - 1] = '\0';
|
||||
}
|
||||
DEBUG("%s Shader Compile Log: %s", name, log);
|
||||
}
|
||||
free(log);
|
||||
|
||||
// Check Status
|
||||
GLint is_compiled = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_COMPILE_STATUS, &is_compiled);
|
||||
if (!is_compiled) {
|
||||
ERR("Failed To Compile %s Shader", name);
|
||||
}
|
||||
}
|
||||
static GLuint compile_shader(const char *vertex_shader_text, const int vertex_shader_length, const char *fragment_shader_text, const int fragment_shader_length) {
|
||||
// Vertex Shader
|
||||
const GLuint vertex_shader = real_glCreateShader()(REAL_GL_VERTEX_SHADER);
|
||||
real_glShaderSource()(vertex_shader, 1, &vertex_shader_text, &vertex_shader_length);
|
||||
real_glCompileShader()(vertex_shader);
|
||||
log_shader(vertex_shader, "Vertex");
|
||||
|
||||
// Fragment Shader
|
||||
const GLuint fragment_shader = real_glCreateShader()(REAL_GL_FRAGMENT_SHADER);
|
||||
real_glShaderSource()(fragment_shader, 1, &fragment_shader_text, &fragment_shader_length);
|
||||
real_glCompileShader()(fragment_shader);
|
||||
log_shader(fragment_shader, "Fragment");
|
||||
|
||||
// Link
|
||||
GLuint program = real_glCreateProgram()();
|
||||
real_glAttachShader()(program, vertex_shader);
|
||||
real_glAttachShader()(program, fragment_shader);
|
||||
real_glLinkProgram()(program);
|
||||
|
||||
// Return
|
||||
return program;
|
||||
}
|
||||
|
||||
// Reset Static Variables
|
||||
typedef struct {
|
||||
GLint *variable;
|
||||
GLint default_value;
|
||||
} static_variable_t;
|
||||
static static_variable_t variables_to_reset[64];
|
||||
static int variables_to_reset_size = 0;
|
||||
static void mark_for_reset(GLint *variable) {
|
||||
static_variable_t variable_obj;
|
||||
variable_obj.variable = variable;
|
||||
variable_obj.default_value = *variable;
|
||||
variables_to_reset[variables_to_reset_size++] = variable_obj;
|
||||
}
|
||||
static void reset_variables() {
|
||||
for (int i = 0; i < variables_to_reset_size; i++) {
|
||||
static_variable_t variable_obj = variables_to_reset[i];
|
||||
*variable_obj.variable = variable_obj.default_value;
|
||||
}
|
||||
variables_to_reset_size = 0;
|
||||
}
|
||||
|
||||
// Shader
|
||||
extern unsigned char main_vsh[];
|
||||
extern size_t main_vsh_len;
|
||||
extern unsigned char main_fsh[];
|
||||
extern size_t main_fsh_len;
|
||||
static GLuint get_shader() {
|
||||
static GLuint program = 0;
|
||||
if (program == 0) {
|
||||
mark_for_reset((GLint *) &program);
|
||||
program = compile_shader((const char *) main_vsh, main_vsh_len, (const char *) main_fsh, main_fsh_len);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// Init
|
||||
GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays));
|
||||
GL_FUNC(glBindVertexArray, void, (GLuint array));
|
||||
GL_FUNC(glActiveTexture, void, (GLenum texture));
|
||||
void init_gles_compatibility_layer() {
|
||||
// State
|
||||
_init_gles_compatibility_layer_state();
|
||||
|
||||
// Reset Static Variables
|
||||
reset_variables();
|
||||
|
||||
// Setup VAO
|
||||
GLuint vao;
|
||||
real_glGenVertexArrays()(1, &vao);
|
||||
real_glBindVertexArray()(vao);
|
||||
|
||||
// Load Shader
|
||||
GLuint program = get_shader();
|
||||
real_glUseProgram()(program);
|
||||
}
|
||||
|
||||
// Array Pointer Drawing
|
||||
GL_FUNC(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count));
|
||||
#define lazy_handle(function, name) \
|
||||
static GLint name##_handle = -1; \
|
||||
if (name##_handle == -1) { \
|
||||
mark_for_reset(&name##_handle); \
|
||||
name##_handle = real_##function()(program, #name); \
|
||||
if (name##_handle == -1) { \
|
||||
ERR("Unable To Find: %s", #name); \
|
||||
} \
|
||||
}
|
||||
#define lazy_uniform(name) lazy_handle(glGetUniformLocation, name)
|
||||
#define lazy_attrib(name) lazy_handle(glGetAttribLocation, name)
|
||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
// Verify
|
||||
if (gl_state.array_pointers.vertex.size != 3 || !gl_state.array_pointers.vertex.enabled || gl_state.array_pointers.vertex.type != GL_FLOAT) {
|
||||
ERR("Unsupported Vertex Conifguration");
|
||||
}
|
||||
|
||||
// Check
|
||||
GLint current_buffer;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer);
|
||||
if (current_buffer == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check Mode
|
||||
int use_color_pointer = gl_state.array_pointers.color.enabled;
|
||||
if (use_color_pointer && (gl_state.array_pointers.color.size != 4 || gl_state.array_pointers.color.type != GL_UNSIGNED_BYTE)) {
|
||||
ERR("Unsupported Color Conifguration");
|
||||
}
|
||||
int use_normal_pointer = gl_state.lighting.enabled && gl_state.array_pointers.normal.enabled;
|
||||
if (use_normal_pointer && gl_state.array_pointers.normal.type != GL_BYTE) {
|
||||
ERR("Unsupported Normal Conifguration");
|
||||
}
|
||||
int use_texture = gl_state.texture_2d && gl_state.array_pointers.tex_coord.enabled;
|
||||
if (use_texture && (gl_state.array_pointers.tex_coord.size != 2 || gl_state.array_pointers.tex_coord.type != GL_FLOAT)) {
|
||||
ERR("Unsupported Texture Conifguration");
|
||||
}
|
||||
|
||||
// Get Shader
|
||||
GLuint program = get_shader();
|
||||
|
||||
// Projection Matrix
|
||||
lazy_uniform(u_projection);
|
||||
matrix_t *projection = &gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i];
|
||||
real_glUniformMatrix4fv()(u_projection_handle, 1, 0, (GLfloat *) &projection->data[0][0]);
|
||||
|
||||
// Model View Matrix
|
||||
lazy_uniform(u_model_view);
|
||||
matrix_t *model_view = &gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
|
||||
real_glUniformMatrix4fv()(u_model_view_handle, 1, 0, (GLfloat *) &model_view->data[0][0]);
|
||||
|
||||
// Has Texture
|
||||
lazy_uniform(u_has_texture); \
|
||||
real_glUniform1i()(u_has_texture_handle, use_texture); \
|
||||
|
||||
// Texture Matrix
|
||||
lazy_uniform(u_texture);
|
||||
matrix_t *texture = &gl_state.matrix_stacks.texture.stack[gl_state.matrix_stacks.texture.i];
|
||||
real_glUniformMatrix4fv()(u_texture_handle, 1, 0, (GLfloat *) &texture->data[0][0]);
|
||||
|
||||
// Texture Unit
|
||||
lazy_uniform(u_texture_unit);
|
||||
real_glUniform1i()(u_texture_unit_handle, 0);
|
||||
|
||||
// Alpha Test
|
||||
lazy_uniform(u_alpha_test);
|
||||
real_glUniform1i()(u_alpha_test_handle, gl_state.alpha_test);
|
||||
|
||||
// Color
|
||||
lazy_attrib(a_color);
|
||||
if (use_color_pointer) {
|
||||
real_glVertexAttribPointer()(a_color_handle, gl_state.array_pointers.color.size, gl_state.array_pointers.color.type, 1, gl_state.array_pointers.color.stride, gl_state.array_pointers.color.pointer);
|
||||
real_glEnableVertexAttribArray()(a_color_handle);
|
||||
} else {
|
||||
real_glVertexAttrib4f()(a_color_handle, gl_state.color.red, gl_state.color.green, gl_state.color.blue, gl_state.color.alpha);
|
||||
}
|
||||
|
||||
// Highlight Mode
|
||||
lazy_uniform(u_highlight_mode);
|
||||
real_glUniform1i()(u_highlight_mode_handle, gl_state.highlight_mode.enabled);
|
||||
if (gl_state.highlight_mode.enabled) {
|
||||
lazy_uniform(u_highlight_mode_color);
|
||||
real_glUniform4f()(u_highlight_mode_color_handle, gl_state.highlight_mode.color.red, gl_state.highlight_mode.color.green, gl_state.highlight_mode.color.blue, gl_state.highlight_mode.color.alpha);
|
||||
}
|
||||
|
||||
// Lighting
|
||||
lazy_uniform(u_lighting);
|
||||
real_glUniform1i()(u_lighting_handle, gl_state.lighting.enabled);
|
||||
lazy_attrib(a_normal);
|
||||
if (gl_state.lighting.enabled) {
|
||||
lazy_uniform(u_lighting_ambient);
|
||||
real_glUniform4f()(u_lighting_ambient_handle, gl_state.lighting.ambient.red, gl_state.lighting.ambient.green, gl_state.lighting.ambient.blue, gl_state.lighting.ambient.alpha);
|
||||
light_source_t *light_source;
|
||||
#define light_source_uniforms(number) \
|
||||
light_source = &gl_state.lighting.light_sources[number]; \
|
||||
lazy_uniform(u_lighting_light_source_##number); \
|
||||
real_glUniform1i()(u_lighting_light_source_##number##_handle, light_source->enabled); \
|
||||
lazy_uniform(u_lighting_light_source_##number##_position); \
|
||||
real_glUniform3f()(u_lighting_light_source_##number##_position_handle, light_source->position.x, light_source->position.y, light_source->position.z); \
|
||||
lazy_uniform(u_lighting_light_source_##number##_diffuse); \
|
||||
real_glUniform4f()(u_lighting_light_source_##number##_diffuse_handle, light_source->diffuse.red, light_source->diffuse.green, light_source->diffuse.blue, light_source->diffuse.alpha);
|
||||
light_source_uniforms(0);
|
||||
light_source_uniforms(1);
|
||||
|
||||
// Normal
|
||||
if (use_normal_pointer) {
|
||||
real_glVertexAttribPointer()(a_normal_handle, 3, gl_state.array_pointers.normal.type, 1, gl_state.array_pointers.normal.stride, gl_state.array_pointers.normal.pointer);
|
||||
real_glEnableVertexAttribArray()(a_normal_handle);
|
||||
} else {
|
||||
real_glVertexAttrib3f()(a_normal_handle, gl_state.normal.x, gl_state.normal.y, gl_state.normal.z);
|
||||
}
|
||||
// Normal Rescale Factor (See Pages 46-47 Of https://registry.khronos.org/OpenGL/specs/gl/glspec15.pdf)
|
||||
float normal_rescale_factor = 1;
|
||||
if (gl_state.rescale_normal) {
|
||||
normal_rescale_factor = 1.0f / sqrtf(powf(model_view->data[0][2], 2) + powf(model_view->data[1][2], 2) + powf(model_view->data[2][2], 2));
|
||||
}
|
||||
lazy_uniform(u_normal_rescale_factor);
|
||||
real_glUniform1f()(u_normal_rescale_factor_handle, normal_rescale_factor);
|
||||
}
|
||||
|
||||
// Fog
|
||||
lazy_uniform(u_fog);
|
||||
real_glUniform1i()(u_fog_handle, gl_state.fog.enabled);
|
||||
if (gl_state.fog.enabled) {
|
||||
lazy_uniform(u_fog_color);
|
||||
real_glUniform4f()(u_fog_color_handle, gl_state.fog.color.red, gl_state.fog.color.green, gl_state.fog.color.blue, gl_state.fog.color.alpha);
|
||||
lazy_uniform(u_fog_is_linear);
|
||||
real_glUniform1i()(u_fog_is_linear_handle, gl_state.fog.mode == GL_LINEAR);
|
||||
lazy_uniform(u_fog_start);
|
||||
real_glUniform1f()(u_fog_start_handle, gl_state.fog.start);
|
||||
lazy_uniform(u_fog_end);
|
||||
real_glUniform1f()(u_fog_end_handle, gl_state.fog.end);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
lazy_attrib(a_vertex_coords);
|
||||
real_glVertexAttribPointer()(a_vertex_coords_handle, gl_state.array_pointers.vertex.size, gl_state.array_pointers.vertex.type, 0, gl_state.array_pointers.vertex.stride, gl_state.array_pointers.vertex.pointer);
|
||||
real_glEnableVertexAttribArray()(a_vertex_coords_handle);
|
||||
|
||||
// Texture Coordinates
|
||||
lazy_attrib(a_texture_coords);
|
||||
if (use_texture) {
|
||||
real_glVertexAttribPointer()(a_texture_coords_handle, gl_state.array_pointers.tex_coord.size, gl_state.array_pointers.tex_coord.type, 0, gl_state.array_pointers.tex_coord.stride, gl_state.array_pointers.tex_coord.pointer);
|
||||
real_glEnableVertexAttribArray()(a_texture_coords_handle);
|
||||
} else {
|
||||
real_glVertexAttrib3f()(a_texture_coords_handle, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Draw
|
||||
real_glDrawArrays()(mode, first, count);
|
||||
|
||||
// Cleanup
|
||||
if (use_color_pointer) {
|
||||
real_glDisableVertexAttribArray()(a_color_handle);
|
||||
}
|
||||
if (use_normal_pointer) {
|
||||
real_glDisableVertexAttribArray()(a_normal_handle);
|
||||
}
|
||||
real_glDisableVertexAttribArray()(a_vertex_coords_handle);
|
||||
if (use_texture) {
|
||||
real_glDisableVertexAttribArray()(a_texture_coords_handle);
|
||||
}
|
||||
}
|
22
src/log.h
Normal file
22
src/log.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
|
||||
#define DEBUG(...) { ((void) __android_log_print(ANDROID_LOG_VERBOSE, "GL DEBUG", __VA_ARGS__)); }
|
||||
#define ERR(...) { ((void) __android_log_print(ANDROID_LOG_ERROR, "GL ERROR", __VA_ARGS__)); exit(EXIT_FAILURE); }
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEBUG(format, ...) { printf("GL DEBUG: " format "\n", ##__VA_ARGS__); }
|
||||
#define ERR(format, ...) { printf("GL ERROR: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
#endif
|
||||
|
||||
#define ALLOC_CHECK(obj) \
|
||||
{ \
|
||||
if (obj == NULL) { \
|
||||
ERR("Memory Allocation Failed"); \
|
||||
} \
|
||||
}
|
131
src/matrix.c
Normal file
131
src/matrix.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "state.h"
|
||||
|
||||
// Matrix Common
|
||||
static void matrix_copy(matrix_t *src, matrix_t *dst) {
|
||||
memcpy((void *) dst->data, (void *) src->data, MATRIX_DATA_SIZE);
|
||||
}
|
||||
|
||||
// Identity Matrix
|
||||
static matrix_t identity_matrix = {
|
||||
.data = {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 0, 1}
|
||||
}
|
||||
};
|
||||
static void init_matrix_stack(matrix_stack_t *stack) {
|
||||
matrix_copy(&identity_matrix, &stack->stack[0]);
|
||||
}
|
||||
void _init_gles_compatibility_matrix_stacks() {
|
||||
init_matrix_stack(&gl_state.matrix_stacks.model_view);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.projection);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.texture);
|
||||
}
|
||||
|
||||
// Matrix Mode
|
||||
static matrix_stack_t *get_matrix_stack() {
|
||||
switch (gl_state.matrix_stacks.mode) {
|
||||
case GL_MODELVIEW: {
|
||||
return &gl_state.matrix_stacks.model_view;
|
||||
}
|
||||
case GL_PROJECTION: {
|
||||
return &gl_state.matrix_stacks.projection;
|
||||
}
|
||||
case GL_TEXTURE: {
|
||||
return &gl_state.matrix_stacks.texture;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Matrix Mode: %i", gl_state.matrix_stacks.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Matrix Functions
|
||||
void glMatrixMode(GLenum mode) {
|
||||
gl_state.matrix_stacks.mode = mode;
|
||||
}
|
||||
void glPopMatrix() {
|
||||
get_matrix_stack()->i--;
|
||||
}
|
||||
void glLoadIdentity() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&identity_matrix, &stack->stack[stack->i]);
|
||||
}
|
||||
void glPushMatrix() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&stack->stack[stack->i], &stack->stack[stack->i + 1]);
|
||||
stack->i++;
|
||||
}
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
matrix_t new_matrix;
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_t *current_matrix = &stack->stack[stack->i];
|
||||
for (int x = 0; x < MATRIX_SIZE; x++) {
|
||||
for (int y = 0; y < MATRIX_SIZE; y++) {
|
||||
GLfloat result = 0;
|
||||
for (int i = 0; i < MATRIX_SIZE; i++) {
|
||||
result += (current_matrix->data[i][y] * m[(x * MATRIX_SIZE) + i]);
|
||||
}
|
||||
new_matrix.data[x][y] = result;
|
||||
}
|
||||
}
|
||||
matrix_copy(&new_matrix, current_matrix);
|
||||
}
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
x, 0, 0, 0,
|
||||
0, y, 0, 0,
|
||||
0, 0, z, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
x, y, z, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) {
|
||||
GLfloat m[] = {
|
||||
(2.f / (right - left)), 0, 0, 0,
|
||||
0, (2.f / (top - bottom)), 0, 0,
|
||||
0, 0, (-2.f / (far - near)), 0,
|
||||
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
#define DEG2RAD (M_PI / 180.f)
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
// Normalize
|
||||
GLfloat length = sqrtf((x * x) + (y * y) + (z * z));
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
|
||||
// Values
|
||||
GLfloat angle_radians = angle * DEG2RAD;
|
||||
GLfloat c = cosf(angle_radians);
|
||||
GLfloat s = sinf(angle_radians);
|
||||
GLfloat x2 = x * x;
|
||||
GLfloat y2 = y * y;
|
||||
GLfloat z2 = z * z;
|
||||
|
||||
// Multiply
|
||||
GLfloat m[] = {
|
||||
x2 * (1.f - c) + c, (x * y) * (1.f - c) + (z * s), (x * z) * (1.f - c) - (y * s), 0,
|
||||
(x * y) * (1.f - c) - (z * s), y2 * (1.f - c) + c, (y * z) * (1.f - c) + (x * s), 0,
|
||||
(x * z) * (1.f - c) + (y * s), (y * z) * (1.f - c) - (x * s), z2 * (1.f - c) + c, 0,
|
||||
0, 0, 0, 1.f
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
9
src/matrix.h
Normal file
9
src/matrix.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
// Matrix Common
|
||||
#define MATRIX_SIZE 4
|
||||
#define MATRIX_DATA_SIZE (sizeof (GLfloat) * MATRIX_SIZE * MATRIX_SIZE)
|
||||
// OpenGL Matrices Are Column-Major
|
||||
typedef struct {
|
||||
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
|
||||
} matrix_t;
|
146
src/passthrough.c
Normal file
146
src/passthrough.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "passthrough.h"
|
||||
|
||||
// Simple v1.1 -> v2.0 Passthrough Functions
|
||||
GL_FUNC(glLineWidth, void, (GLfloat width));
|
||||
void glLineWidth(GLfloat width) {
|
||||
real_glLineWidth()(width);
|
||||
}
|
||||
GL_FUNC(glBlendFunc, void, (GLenum sfactor, GLenum dfactor));
|
||||
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
real_glBlendFunc()(sfactor, dfactor);
|
||||
}
|
||||
GL_FUNC(glClear, void, (GLbitfield mask));
|
||||
void glClear(GLbitfield mask) {
|
||||
real_glClear()(mask);
|
||||
}
|
||||
GL_FUNC(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage));
|
||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
||||
real_glBufferData()(target, size, data, usage);
|
||||
}
|
||||
GL_FUNC(glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glScissor()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glTexParameteri, void, (GLenum target, GLenum pname, GLint param));
|
||||
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
real_glTexParameteri()(target, pname, param);
|
||||
}
|
||||
GL_FUNC(glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexImage2D()(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glPolygonOffset, void, (GLfloat factor, GLfloat units));
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units) {
|
||||
real_glPolygonOffset()(factor, units);
|
||||
}
|
||||
GL_FUNC(glDepthRangef, void, (GLclampf near, GLclampf far));
|
||||
void glDepthRangef(GLclampf near, GLclampf far) {
|
||||
real_glDepthRangef()(near, far);
|
||||
}
|
||||
GL_FUNC(glBindBuffer, void, (GLenum target, GLuint buffer));
|
||||
void glBindBuffer(GLenum target, GLuint buffer) {
|
||||
real_glBindBuffer()(target, buffer);
|
||||
}
|
||||
GL_FUNC(glDepthFunc, void, (GLenum func));
|
||||
void glDepthFunc(GLenum func) {
|
||||
real_glDepthFunc()(func);
|
||||
}
|
||||
GL_FUNC(glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
|
||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
||||
real_glClearColor()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glDepthMask, void, (GLboolean flag));
|
||||
void glDepthMask(GLboolean flag) {
|
||||
real_glDepthMask()(flag);
|
||||
}
|
||||
GL_FUNC(glHint, void, (GLenum target, GLenum mode));
|
||||
void glHint(GLenum target, GLenum mode) {
|
||||
if (target != GL_PERSPECTIVE_CORRECTION_HINT) {
|
||||
real_glHint()(target, mode);
|
||||
}
|
||||
}
|
||||
GL_FUNC(glDeleteBuffers, void, (GLsizei n, const GLuint *buffers));
|
||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers) {
|
||||
real_glDeleteBuffers()(n, buffers);
|
||||
}
|
||||
GL_FUNC(glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha));
|
||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
||||
real_glColorMask()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexSubImage2D()(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glGenTextures, void, (GLsizei n, GLuint *textures));
|
||||
void glGenTextures(GLsizei n, GLuint *textures) {
|
||||
real_glGenTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glDeleteTextures, void, (GLsizei n, const GLuint *textures));
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures) {
|
||||
real_glDeleteTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glBindTexture, void, (GLenum target, GLuint texture));
|
||||
void glBindTexture(GLenum target, GLuint texture) {
|
||||
real_glBindTexture()(target, texture);
|
||||
}
|
||||
GL_FUNC(glCullFace, void, (GLenum mode));
|
||||
void glCullFace(GLenum mode) {
|
||||
real_glCullFace()(mode);
|
||||
}
|
||||
GL_FUNC(glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glViewport()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glIsEnabled, GLboolean, (GLenum cap));
|
||||
GLboolean glIsEnabled(GLenum cap) {
|
||||
return real_glIsEnabled()(cap);
|
||||
}
|
||||
GL_FUNC(glGetIntegerv, void, (GLenum pname, GLint *data));
|
||||
void glGetIntegerv(GLenum pname, GLint *data) {
|
||||
real_glGetIntegerv()(pname, data);
|
||||
}
|
||||
GL_FUNC(glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data));
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data) {
|
||||
real_glReadPixels()(x, y, width, height, format, type, data);
|
||||
}
|
||||
void glShadeModel(__attribute__((unused)) GLenum mode) {
|
||||
// Do Nothing
|
||||
}
|
||||
GL_FUNC(glGenBuffers, void, (GLsizei n, GLuint *buffers));
|
||||
void glGenBuffers(GLsizei n, GLuint *buffers) {
|
||||
real_glGenBuffers()(n, buffers);
|
||||
}
|
||||
GL_FUNC(glGetError, GLenum, ());
|
||||
GLenum glGetError() {
|
||||
return real_glGetError()();
|
||||
}
|
||||
GL_FUNC(glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size, const void *data));
|
||||
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
|
||||
real_glBufferSubData()(target, offset, size, data);
|
||||
}
|
||||
GL_FUNC(glGenQueries, void, (GLsizei n, GLuint *ids));
|
||||
void glGenQueriesARB(GLsizei n, GLuint *ids) {
|
||||
real_glGenQueries()(n, ids);
|
||||
}
|
||||
GL_FUNC(glDeleteQueries, void, (GLsizei n, const GLuint *ids));
|
||||
void glDeleteQueriesARB(GLsizei n, const GLuint *ids) {
|
||||
real_glDeleteQueries()(n, ids);
|
||||
}
|
||||
GL_FUNC(glBeginQuery, void, (GLenum target, GLuint id));
|
||||
void glBeginQueryARB(GLenum target, GLuint id) {
|
||||
real_glBeginQuery()(target, id);
|
||||
}
|
||||
GL_FUNC(glEndQuery, void, (GLenum target));
|
||||
void glEndQueryARB(GLenum target) {
|
||||
real_glEndQuery()(target);
|
||||
}
|
||||
GL_FUNC(glGetQueryObjectuiv, void, (GLuint id, GLenum pname, GLuint *params));
|
||||
void glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) {
|
||||
real_glGetQueryObjectuiv()(id, pname, params);
|
||||
}
|
||||
GL_FUNC(glPixelStorei, void, (GLenum pname, GLint param));
|
||||
void glPixelStorei(GLenum pname, GLint param) {
|
||||
real_glPixelStorei()(pname, param);
|
||||
}
|
23
src/passthrough.h
Normal file
23
src/passthrough.h
Normal file
@ -0,0 +1,23 @@
|
||||
#include <SDL.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
// Load GL Function
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
#define GL_APIENTRY __stdcall
|
||||
#else
|
||||
#define GL_APIENTRY
|
||||
#endif
|
||||
#define GL_FUNC(name, return_type, args) \
|
||||
typedef return_type (GL_APIENTRY *real_##name##_t)args; \
|
||||
\
|
||||
real_##name##_t real_##name() { \
|
||||
static real_##name##_t func = NULL; \
|
||||
if (!func) { \
|
||||
func = (real_##name##_t) SDL_GL_GetProcAddress(#name); \
|
||||
if (!func) { \
|
||||
ERR("Error Resolving GL Symbol: " #name); \
|
||||
} \
|
||||
} \
|
||||
return func; \
|
||||
}
|
52
src/shaders/main.fsh
Normal file
52
src/shaders/main.fsh
Normal file
@ -0,0 +1,52 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
// Result
|
||||
out vec4 frag_color;
|
||||
// Texture
|
||||
uniform bool u_has_texture;
|
||||
uniform sampler2D u_texture_unit;
|
||||
// Color
|
||||
in vec4 v_color;
|
||||
in 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;
|
||||
in vec4 v_fog_eye_position;
|
||||
// Main
|
||||
void main(void) {
|
||||
frag_color = 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;
|
||||
frag_color = texture_color;
|
||||
} else {
|
||||
frag_color *= 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);
|
||||
frag_color.rgb = mix(frag_color, u_fog_color, 1.0 - fog_factor).rgb;
|
||||
}
|
||||
// Alpha Test
|
||||
if (u_alpha_test && frag_color.a <= 0.1) {
|
||||
discard;
|
||||
}
|
||||
}
|
48
src/shaders/main.vsh
Normal file
48
src/shaders/main.vsh
Normal file
@ -0,0 +1,48 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
// Matrices
|
||||
uniform mat4 u_projection;
|
||||
uniform mat4 u_model_view;
|
||||
uniform mat4 u_texture;
|
||||
// Texture
|
||||
in vec3 a_vertex_coords;
|
||||
in vec2 a_texture_coords;
|
||||
out vec4 v_texture_pos;
|
||||
// Color
|
||||
in vec4 a_color;
|
||||
out vec4 v_color;
|
||||
// Normal
|
||||
in 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
|
||||
out 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;
|
||||
}
|
||||
}
|
336
src/state.c
Normal file
336
src/state.c
Normal file
@ -0,0 +1,336 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "state.h"
|
||||
#include "passthrough.h"
|
||||
|
||||
// GL State
|
||||
#define init_array_pointer \
|
||||
{ \
|
||||
.enabled = 0 \
|
||||
}
|
||||
#define init_light_source \
|
||||
.enabled = 0, \
|
||||
.position = { \
|
||||
.x = 0, \
|
||||
.y = 0, \
|
||||
.z = 1 \
|
||||
}
|
||||
static gl_state_t init_gl_state = {
|
||||
.color = {
|
||||
.red = 1,
|
||||
.green = 1,
|
||||
.blue = 1,
|
||||
.alpha = 1
|
||||
},
|
||||
.normal = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.z = 1
|
||||
},
|
||||
.rescale_normal = 0,
|
||||
.array_pointers = {
|
||||
.vertex = init_array_pointer,
|
||||
.color = init_array_pointer,
|
||||
.tex_coord = init_array_pointer,
|
||||
.normal = init_array_pointer
|
||||
},
|
||||
.matrix_stacks = {
|
||||
.mode = GL_MODELVIEW
|
||||
},
|
||||
.alpha_test = 0,
|
||||
.texture_2d = 0,
|
||||
.fog = {
|
||||
.enabled = 0,
|
||||
.mode = GL_LINEAR,
|
||||
.color = {
|
||||
.red = 0,
|
||||
.green = 0,
|
||||
.blue = 0,
|
||||
.alpha = 0
|
||||
},
|
||||
.start = 0,
|
||||
.end = 1
|
||||
},
|
||||
.lighting = {
|
||||
.enabled = 0,
|
||||
.light_sources = {
|
||||
{
|
||||
init_light_source,
|
||||
.diffuse = {
|
||||
.red = 1,
|
||||
.green = 1,
|
||||
.blue = 1,
|
||||
.alpha = 1
|
||||
}
|
||||
},
|
||||
{
|
||||
init_light_source,
|
||||
.diffuse = {
|
||||
.red = 0,
|
||||
.green = 0,
|
||||
.blue = 0,
|
||||
.alpha = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
.ambient = {
|
||||
.red = 0.2f,
|
||||
.green = 0.2f,
|
||||
.blue = 0.2f,
|
||||
.alpha = 0.2f
|
||||
}
|
||||
},
|
||||
.highlight_mode = {
|
||||
.enabled = 0
|
||||
}
|
||||
};
|
||||
gl_state_t gl_state;
|
||||
void _init_gles_compatibility_layer_state() {
|
||||
gl_state = init_gl_state;
|
||||
_init_gles_compatibility_matrix_stacks();
|
||||
}
|
||||
|
||||
// Change Color
|
||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
gl_state.color.red = red;
|
||||
gl_state.color.green = green;
|
||||
gl_state.color.blue = blue;
|
||||
gl_state.color.alpha = alpha;
|
||||
}
|
||||
|
||||
// Change Normal
|
||||
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) {
|
||||
gl_state.normal.x = nx;
|
||||
gl_state.normal.y = ny;
|
||||
gl_state.normal.z = nz;
|
||||
}
|
||||
|
||||
// Array Pointer Storage
|
||||
#define ARRAY_POINTER_FUNC(func, name) \
|
||||
void func(GLint size, GLenum type, GLsizei stride, const void *pointer) { \
|
||||
gl_state.array_pointers.name.size = size; \
|
||||
gl_state.array_pointers.name.type = type; \
|
||||
gl_state.array_pointers.name.stride = stride; \
|
||||
gl_state.array_pointers.name.pointer = pointer; \
|
||||
}
|
||||
ARRAY_POINTER_FUNC(glVertexPointer, vertex)
|
||||
ARRAY_POINTER_FUNC(glColorPointer, color)
|
||||
ARRAY_POINTER_FUNC(glTexCoordPointer, tex_coord)
|
||||
static ARRAY_POINTER_FUNC(fake_glNormalPointer, normal)
|
||||
void glNormalPointer(GLenum type, GLsizei stride, const void *pointer) {
|
||||
fake_glNormalPointer(0, type, stride, pointer);
|
||||
}
|
||||
static array_pointer_t *get_array_pointer(GLenum array) {
|
||||
switch (array) {
|
||||
case GL_VERTEX_ARRAY: {
|
||||
return &gl_state.array_pointers.vertex;
|
||||
}
|
||||
case GL_COLOR_ARRAY: {
|
||||
return &gl_state.array_pointers.color;
|
||||
}
|
||||
case GL_TEXTURE_COORD_ARRAY: {
|
||||
return &gl_state.array_pointers.tex_coord;
|
||||
}
|
||||
case GL_NORMAL_ARRAY: {
|
||||
return &gl_state.array_pointers.normal;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Array Pointer: %i", array);
|
||||
}
|
||||
}
|
||||
}
|
||||
void glEnableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 1;
|
||||
}
|
||||
void glDisableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 0;
|
||||
}
|
||||
|
||||
// Enable/Disable State
|
||||
GL_FUNC(glEnable, void, (GLenum cap));
|
||||
void glEnable(GLenum cap) {
|
||||
switch (cap) {
|
||||
case GL_ALPHA_TEST: {
|
||||
gl_state.alpha_test = 1;
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D: {
|
||||
gl_state.texture_2d = 1;
|
||||
break;
|
||||
}
|
||||
case GL_RESCALE_NORMAL: {
|
||||
gl_state.rescale_normal = 1;
|
||||
break;
|
||||
}
|
||||
case GL_COLOR_MATERIAL: {
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
case GL_FOG: {
|
||||
gl_state.fog.enabled = 1;
|
||||
break;
|
||||
}
|
||||
case GL_LIGHTING: {
|
||||
gl_state.lighting.enabled = 1;
|
||||
break;
|
||||
}
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1: {
|
||||
gl_state.lighting.light_sources[cap - GL_LIGHT0].enabled = 1;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glEnable()(cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GL_FUNC(glDisable, void, (GLenum cap));
|
||||
void glDisable(GLenum cap) {
|
||||
switch (cap) {
|
||||
case GL_ALPHA_TEST: {
|
||||
gl_state.alpha_test = 0;
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D: {
|
||||
gl_state.texture_2d = 0;
|
||||
break;
|
||||
}
|
||||
case GL_RESCALE_NORMAL: {
|
||||
gl_state.rescale_normal = 0;
|
||||
break;
|
||||
}
|
||||
case GL_COLOR_MATERIAL: {
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
case GL_FOG: {
|
||||
gl_state.fog.enabled = 0;
|
||||
break;
|
||||
}
|
||||
case GL_LIGHTING: {
|
||||
gl_state.lighting.enabled = 0;
|
||||
break;
|
||||
}
|
||||
case GL_LIGHT0:
|
||||
case GL_LIGHT1: {
|
||||
gl_state.lighting.light_sources[cap - GL_LIGHT0].enabled = 0;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glDisable()(cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void glAlphaFunc(GLenum func, GLclampf ref) {
|
||||
if (func != GL_GREATER && ref != 0.1f) {
|
||||
ERR("Unsupported Alpha Function");
|
||||
}
|
||||
}
|
||||
|
||||
// Fog
|
||||
#define UNSUPPORTED_FOG() ERR("Unsupported Fog Configuration")
|
||||
void glFogfv(GLenum pname, const GLfloat *params) {
|
||||
if (pname == GL_FOG_COLOR) {
|
||||
gl_state.fog.color.red = params[0];
|
||||
gl_state.fog.color.green = params[1];
|
||||
gl_state.fog.color.blue = params[2];
|
||||
gl_state.fog.color.alpha = params[3];
|
||||
} else {
|
||||
UNSUPPORTED_FOG();
|
||||
}
|
||||
}
|
||||
void glFogx(GLenum pname, GLfixed param) {
|
||||
if (pname == GL_FOG_MODE && (param == GL_LINEAR || param == GL_EXP)) {
|
||||
gl_state.fog.mode = param;
|
||||
} else {
|
||||
UNSUPPORTED_FOG();
|
||||
}
|
||||
}
|
||||
void glFogf(GLenum pname, GLfloat param) {
|
||||
switch (pname) {
|
||||
case GL_FOG_DENSITY:
|
||||
case GL_FOG_START: {
|
||||
gl_state.fog.start = param;
|
||||
break;
|
||||
}
|
||||
case GL_FOG_END: {
|
||||
gl_state.fog.end = param;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNSUPPORTED_FOG();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Matrix Data
|
||||
GL_FUNC(glGetFloatv, void, (GLenum pname, GLfloat *params));
|
||||
void glGetFloatv(GLenum pname, GLfloat *params) {
|
||||
switch (pname) {
|
||||
case GL_MODELVIEW_MATRIX: {
|
||||
memcpy((void *) params, gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i].data, MATRIX_DATA_SIZE);
|
||||
break;
|
||||
}
|
||||
case GL_PROJECTION_MATRIX: {
|
||||
memcpy((void *) params, gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i].data, MATRIX_DATA_SIZE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glGetFloatv()(pname, params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure Light Sources
|
||||
void glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
||||
light_source_t *light_source = &gl_state.lighting.light_sources[light - GL_LIGHT0];
|
||||
if (pname == GL_DIFFUSE) {
|
||||
light_source->diffuse.red = params[0];
|
||||
light_source->diffuse.green = params[1];
|
||||
light_source->diffuse.blue = params[2];
|
||||
light_source->diffuse.alpha = params[3];
|
||||
} else if (pname == GL_POSITION) {
|
||||
// Transform Position By Modelview Matrix
|
||||
matrix_t model_view = gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
|
||||
GLfloat out[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GLfloat result = 0;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
result += model_view.data[j][i] * params[j];
|
||||
}
|
||||
out[i] = result;
|
||||
}
|
||||
// Store
|
||||
light_source->position.x = out[0];
|
||||
light_source->position.y = out[1];
|
||||
light_source->position.z = out[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Global Ambient Lighting
|
||||
void glLightModelfv(GLenum pname, const GLfloat *params) {
|
||||
if (pname == GL_LIGHT_MODEL_AMBIENT) {
|
||||
gl_state.lighting.ambient.red = params[0];
|
||||
gl_state.lighting.ambient.green = params[1];
|
||||
gl_state.lighting.ambient.blue = params[2];
|
||||
gl_state.lighting.ambient.alpha = params[3];
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight Mode
|
||||
void extra_enable_highlight_mode(float red, float green, float blue, float alpha) {
|
||||
gl_state.highlight_mode.enabled = 1;
|
||||
gl_state.highlight_mode.color.red = red;
|
||||
gl_state.highlight_mode.color.green = green;
|
||||
gl_state.highlight_mode.color.blue = blue;
|
||||
gl_state.highlight_mode.color.alpha = alpha;
|
||||
}
|
||||
void extra_disable_highlight_mode() {
|
||||
gl_state.highlight_mode.enabled = 0;
|
||||
}
|
81
src/state.h
Normal file
81
src/state.h
Normal file
@ -0,0 +1,81 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
// Matrix Data
|
||||
#define MATRIX_STACK_DEPTH 256
|
||||
typedef struct {
|
||||
matrix_t stack[MATRIX_STACK_DEPTH];
|
||||
unsigned int i;
|
||||
} matrix_stack_t;
|
||||
|
||||
// Position
|
||||
typedef struct {
|
||||
GLfloat x;
|
||||
GLfloat y;
|
||||
GLfloat z;
|
||||
} position_t;
|
||||
|
||||
// Color
|
||||
typedef struct {
|
||||
GLfloat red;
|
||||
GLfloat green;
|
||||
GLfloat blue;
|
||||
GLfloat alpha;
|
||||
} color_t;
|
||||
|
||||
// Array Pointer Storage
|
||||
typedef struct {
|
||||
GLboolean enabled;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
const void *pointer;
|
||||
} array_pointer_t;
|
||||
|
||||
// Light
|
||||
typedef struct {
|
||||
GLboolean enabled;
|
||||
position_t position;
|
||||
color_t diffuse;
|
||||
} light_source_t;
|
||||
|
||||
// GL State
|
||||
typedef struct {
|
||||
color_t color;
|
||||
position_t normal;
|
||||
GLboolean rescale_normal;
|
||||
struct {
|
||||
GLenum mode;
|
||||
matrix_stack_t model_view;
|
||||
matrix_stack_t projection;
|
||||
matrix_stack_t texture;
|
||||
} matrix_stacks;
|
||||
struct {
|
||||
array_pointer_t vertex;
|
||||
array_pointer_t color;
|
||||
array_pointer_t tex_coord;
|
||||
array_pointer_t normal;
|
||||
} array_pointers;
|
||||
GLboolean alpha_test;
|
||||
GLboolean texture_2d;
|
||||
struct {
|
||||
GLboolean enabled;
|
||||
GLfixed mode;
|
||||
color_t color;
|
||||
GLfloat start;
|
||||
GLfloat end;
|
||||
} fog;
|
||||
struct {
|
||||
GLboolean enabled;
|
||||
light_source_t light_sources[2];
|
||||
color_t ambient;
|
||||
} lighting;
|
||||
struct {
|
||||
GLboolean enabled;
|
||||
color_t color;
|
||||
} highlight_mode;
|
||||
} gl_state_t;
|
||||
extern gl_state_t gl_state;
|
||||
void _init_gles_compatibility_layer_state();
|
||||
void _init_gles_compatibility_matrix_stacks();
|
Reference in New Issue
Block a user