334 lines
12 KiB
C++
334 lines
12 KiB
C++
//
|
|
|
|
// TODO(PS):
|
|
// TODO(PS):
|
|
// TODO(PS):
|
|
// TODO(PS): you guessed the data types and names of ALL of this
|
|
// fix it!
|
|
|
|
typedef int GLint;
|
|
typedef unsigned int GLuint;
|
|
typedef float GLfloat;
|
|
typedef unsigned int GLenum;
|
|
typedef bool GLboolean;
|
|
typedef unsigned int GLsizei;
|
|
|
|
// NOTE(PS): these values and function signatures all come from
|
|
// the GLES2/gl2.h header file that can be found here:
|
|
// https://www.khronos.org/registry/OpenGL/api/GLES2/gl2.h
|
|
//
|
|
// I resorted to hard coding these rather than passing them in because
|
|
// passing them in didn't seem to be working.
|
|
|
|
#define GL_FALSE 0
|
|
#define GL_TRUE 1
|
|
#define GL_TEXTURE_2D 0x0DE1
|
|
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
|
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
|
#define GL_COLOR_BUFFER_BIT 0x00004000
|
|
#define GL_BLEND 0x0BE2
|
|
#define GL_SRC_ALPHA 0x0302
|
|
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
|
#define GL_DEPTH_TEST 0x0B71
|
|
#define GL_LESS 0x0201
|
|
#define GL_ARRAY_BUFFER 0x8892
|
|
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
|
#define GL_STATIC_DRAW 0x88e4
|
|
#define GL_FRAGMENT_SHADER 0x8b30
|
|
#define GL_VERTEX_SHADER 0x8b31
|
|
#define GL_TRIANGLES 0x0004
|
|
#define GL_UNSIGNED_INT 0x1405
|
|
#define GL_FLOAT 0x1406
|
|
#define GL_TEXTURE_WRAP_S 0x2802
|
|
#define GL_TEXTURE_WRAP_T 0x2803
|
|
#define GL_REPEAT 0x2901
|
|
#define GL_TEXTURE_MIN_FILTER 0x2801
|
|
#define GL_TEXTURE_MAG_FILTER 0x2800
|
|
#define GL_LINEAR 0x2601
|
|
#define GL_RGB 0x1907
|
|
#define GL_RGBA 0x1908
|
|
#define GL_UNSIGNED_BYTE 0x1401
|
|
#define GL_CLAMP_TO_EDGE 0x812F
|
|
|
|
WASM_EXTERN bool glHadError();
|
|
WASM_EXTERN void glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
|
WASM_EXTERN void glEnable(GLuint i);
|
|
WASM_EXTERN void glDisable(GLuint i);
|
|
WASM_EXTERN void glBlendFunc(GLuint a, GLuint b);
|
|
WASM_EXTERN void glViewport(GLuint xmin, GLuint ymin, GLuint xmax, GLuint ymax);
|
|
WASM_EXTERN void glDepthFunc(GLuint i);
|
|
WASM_EXTERN void glClear(GLuint i);
|
|
|
|
WASM_EXTERN GLuint glCreateBuffer();
|
|
WASM_EXTERN void glBindBuffer(GLenum buffer_kind, GLuint buffer_id);
|
|
WASM_EXTERN void glBufferData(GLenum target, size_t size, const void* data, GLenum usage);
|
|
WASM_EXTERN void glBufferSubData(GLenum target, size_t offset, size_t size, const void* data);
|
|
WASM_EXTERN GLuint glCreateShader(GLenum kind);
|
|
WASM_EXTERN GLuint glShaderSource(GLuint shader_id, char* shader_code, GLuint shader_code_len);
|
|
WASM_EXTERN void glCompileShader(GLuint shader_id);
|
|
WASM_EXTERN GLuint glCreateProgram(void);
|
|
WASM_EXTERN void glAttachShader(GLuint program, GLuint shader);
|
|
WASM_EXTERN void glLinkProgram(GLuint program);
|
|
WASM_EXTERN void glUseProgram(GLuint program);
|
|
WASM_EXTERN GLuint glGetAttribLocation(GLuint program, const char* name, GLuint name_len);
|
|
WASM_EXTERN GLuint glGetUniformLocation(GLuint program, const char* name, u32 len);
|
|
WASM_EXTERN void glUniformMatrix4fv(GLuint uniform, GLuint count, GLenum normalize, GLfloat* elements);
|
|
WASM_EXTERN void glVertexAttribPointer(GLuint attr, GLuint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
|
WASM_EXTERN void glEnableVertexAttribArray(GLuint index);
|
|
WASM_EXTERN void glDrawElements(GLenum type, GLuint count, GLenum ele_type, void* indices);
|
|
WASM_EXTERN void glGenTextures(GLuint count, GLuint* ids, u32 ids_size);
|
|
WASM_EXTERN void glBindTexture(GLenum slot, GLuint id);
|
|
WASM_EXTERN void glTexParameteri(GLenum slot, GLenum param, GLenum value);
|
|
WASM_EXTERN void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * data, u32 data_size);
|
|
WASM_EXTERN void glBindTexture(GLenum target, GLuint id);
|
|
WASM_EXTERN void glTexSubImage2D(GLenum target, GLint level, GLuint offsetx, GLuint offsety, GLuint w, GLuint h, GLenum format, GLenum type, void* ptr, u32 ptr_size);
|
|
|
|
Platform_Geometry_Buffer
|
|
platform_geometry_buffer_create(
|
|
r32* vertices, GLuint vertices_len,
|
|
GLuint* indices, GLuint indices_len
|
|
){
|
|
Platform_Geometry_Buffer result = {};
|
|
|
|
result.buffer_id_vertices = glCreateBuffer();
|
|
result.buffer_id_indices = glCreateBuffer();
|
|
|
|
// Vertices
|
|
glBindBuffer(GL_ARRAY_BUFFER, result.buffer_id_vertices);
|
|
glBufferData(
|
|
GL_ARRAY_BUFFER, sizeof(r32) * vertices_len, vertices, GL_STATIC_DRAW
|
|
);
|
|
|
|
// Indices
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.buffer_id_indices);
|
|
glBufferData(
|
|
GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices_len, indices, GL_STATIC_DRAW
|
|
);
|
|
result.indices_len = indices_len;
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)NULL);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
platform_geometry_buffer_update(
|
|
Platform_Geometry_Buffer* buffer,
|
|
r32* verts,
|
|
u32 verts_offset,
|
|
u32 verts_len,
|
|
u32* indices,
|
|
u32 indices_offset,
|
|
u32 indices_len
|
|
){
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer->buffer_id_vertices);
|
|
if (verts_len > buffer->vertices_len)
|
|
{
|
|
// NOTE(PS): this is because we're going to delete the old buffer and
|
|
// create a new one. In order to do that and not lose data, the update
|
|
// function needs to have been passed all the buffer's data
|
|
assert(verts_offset == 0);
|
|
glBufferData(
|
|
GL_ARRAY_BUFFER, verts_len * sizeof(r32), (void*)verts, GL_STATIC_DRAW
|
|
);
|
|
}
|
|
else
|
|
{
|
|
glBufferSubData(
|
|
GL_ARRAY_BUFFER, verts_offset * sizeof(r32), verts_len * sizeof(r32), (void*)verts
|
|
);
|
|
}
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->buffer_id_indices);
|
|
if (indices_len > buffer->indices_len)
|
|
{
|
|
// NOTE(PS): this is because we're going to delete the old buffer and
|
|
// create a new one. In order to do that and not lose data, the update
|
|
// function needs to have been passed all the buffer's data
|
|
assert(indices_offset == 0);
|
|
glBufferData(
|
|
GL_ELEMENT_ARRAY_BUFFER, indices_len * sizeof(u32), (void*)indices, GL_STATIC_DRAW
|
|
);
|
|
}
|
|
else
|
|
{
|
|
glBufferSubData(
|
|
GL_ELEMENT_ARRAY_BUFFER, indices_offset * sizeof(u32), indices_len * sizeof(u32), (void*)indices
|
|
);
|
|
}
|
|
}
|
|
|
|
Platform_Shader
|
|
platform_shader_create(
|
|
String code_vert, String code_frag, String* attrs, GLuint attrs_len, String* uniforms, GLuint uniforms_len
|
|
){
|
|
Platform_Shader result = {};
|
|
|
|
GLuint shader_vert = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(shader_vert, str_expand(code_vert));
|
|
glCompileShader(shader_vert);
|
|
|
|
GLuint shader_frag = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(shader_frag, str_expand(code_frag));
|
|
glCompileShader(shader_frag);
|
|
|
|
result.id = (GLuint)glCreateProgram();
|
|
glAttachShader(result.id, shader_vert);
|
|
glAttachShader(result.id, shader_frag);
|
|
glLinkProgram(result.id);
|
|
glUseProgram(result.id);
|
|
|
|
// TODO(PS): delete the vert and frag programs
|
|
|
|
assert(attrs_len < PLATFORM_SHADER_MAX_ATTRS);
|
|
for (GLuint i = 0; i < attrs_len; i++)
|
|
{
|
|
s32 len = (s32)attrs[i].len;
|
|
result.attrs[i] = glGetAttribLocation(
|
|
result.id, (char*)attrs[i].str, len
|
|
);
|
|
}
|
|
result.attrs[attrs_len] = PLATFORM_SHADER_ATTR_LAST;
|
|
|
|
assert(uniforms_len < PLATFORM_SHADER_MAX_ATTRS);
|
|
for (GLuint i = 0; i < uniforms_len; i++)
|
|
{
|
|
s32 len = (s32)uniforms[i].len;
|
|
result.uniforms[i] = glGetUniformLocation(
|
|
result.id, (char*)uniforms[i].str, uniforms[i].len
|
|
);
|
|
}
|
|
result.uniforms[uniforms_len] = PLATFORM_SHADER_ATTR_LAST;
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
platform_geometry_bind(Platform_Geometry_Buffer geo)
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, geo.buffer_id_vertices);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geo.buffer_id_indices);
|
|
}
|
|
|
|
void
|
|
platform_shader_bind(Platform_Shader shader)
|
|
{
|
|
glUseProgram(shader.id);
|
|
for (GLuint i = 0; i < PLATFORM_SHADER_MAX_ATTRS && shader.attrs[i] != PLATFORM_SHADER_ATTR_LAST; i++)
|
|
{
|
|
glEnableVertexAttribArray(shader.attrs[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
platform_set_uniform(Platform_Shader shader, u32 index, m44 u)
|
|
{
|
|
glUniformMatrix4fv(shader.uniforms[index], 1, GL_FALSE, (r32*)u.Elements);
|
|
}
|
|
|
|
void
|
|
platform_geometry_draw(
|
|
Platform_Geometry_Buffer geo, u32 indices
|
|
){
|
|
glDrawElements(GL_TRIANGLES, indices, GL_UNSIGNED_INT, 0);
|
|
}
|
|
|
|
void
|
|
platform_geometry_draw(
|
|
Platform_Geometry_Buffer geo
|
|
){
|
|
glDrawElements(GL_TRIANGLES, geo.indices_len, GL_UNSIGNED_INT, 0);
|
|
}
|
|
|
|
void platform_vertex_attrib_pointer(
|
|
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 count, u32 attr_index, u32 stride, u32 offset
|
|
){
|
|
//platform_shader_bind(shader);
|
|
platform_geometry_bind(geo);
|
|
glVertexAttribPointer(shader.attrs[attr_index], count, GL_FLOAT, false, stride * sizeof(float), (void*)(offset * sizeof(float)));
|
|
}
|
|
|
|
Platform_Texture
|
|
platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride)
|
|
{
|
|
Platform_Texture result = {};
|
|
glGenTextures(1, &result.id, sizeof(u32));
|
|
glBindTexture(GL_TEXTURE_2D, result.id);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_UNSIGNED_BYTE,
|
|
pixels,
|
|
(width * height) * sizeof(u32)
|
|
);
|
|
|
|
result.w = width;
|
|
result.h = height;
|
|
result.s = stride;
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
platform_texture_update(Platform_Texture tex, u8* new_pixels, u32 width, u32 height, u32 stride)
|
|
{
|
|
// NOTE(PS): this function simply replaces the entire image
|
|
// we can write a more granular version if we need it
|
|
|
|
assert(tex.w == width && tex.h == height && tex.s == stride);
|
|
platform_texture_bind(tex);
|
|
glTexSubImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
0, 0, // offset
|
|
width, height,
|
|
GL_RGBA,
|
|
GL_UNSIGNED_BYTE,
|
|
new_pixels,
|
|
width * height * sizeof(u32)
|
|
);
|
|
}
|
|
|
|
|
|
void
|
|
platform_texture_bind(Platform_Texture tex)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, tex.id);
|
|
}
|
|
|
|
void
|
|
platform_frame_begin(Platform_Graphics_Frame_Desc desc)
|
|
{
|
|
v4 cc = desc.clear_color;
|
|
glClearColor(cc.r, cc.g, cc.b, cc.a);
|
|
|
|
v2 vmin = desc.viewport_min;
|
|
v2 vmax = desc.viewport_max;
|
|
glViewport(vmin.x, vmin.y, vmax.x, vmax.y);
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
//glDisable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthFunc(GL_LESS);
|
|
}
|
|
|
|
void
|
|
platform_frame_clear()
|
|
{
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
} |