#pragma once #include #include #define GLM_FORCE_XYZW_ONLY #include #include "asset.h" #include "types.h" #include "util.h" enum UniformType { UNIFORM_SAMPLER, UNIFORM_NODE_XFORM, UNIFORM_VIEW_XFORM, UNIFORM_PROJECTION_XFORM, UNIFORM_NORMAL_XFORM, UNIFORM_BLOCK_XFORMS, UNIFORM_BLOCK_LIGHTS, UNIFORM_UNKNOWN, UNIFORM_TYPE_COUNT }; struct GLUniform { // NOTE: would be nice to use idx as the location parameter because it seems // to match when the uniform isn't part of a uniform block, at least with // intel mesa driver, but apparently that's not guarantied GLuint idx; GLint location; GLint block_idx; UniformType uniform_type; GLenum gl_type; // NOTE: GL_UNSIGNED_INT, GL_FLOAT_VEC4 GLint num_elements; // NOTE: 1 unless uniform is an array of base types GLint array_stride; // NOTE: bytes between array elements GLint uniform_offset; // NOTE: byte offset from beginning of uniform char* name; }; struct GLUniformBlock { GLuint block_id; GLint binding_idx; UniformType uniform_type; GLuint num_uniforms; GLUniform* uniforms; char* name; }; enum MeshBufferType { VERTEX, NORMAL, UV, COLOR, MESH_BUFFER_TYPE_COUNT }; // NOTE: we need another struct for vertex attributes that mirrors GLBuffer // because an attribute is associated with a ShaderProgram while a buffer is // associated with the vertex data passed to glBufferData() struct GLVertexAttrib { MeshBufferType buf_type; GLenum data_type; GLenum component_type; u32 num_components; GLuint location; char* name; }; // TODO: add a note explaining usage when we implement complex entities struct GLBufferToAttribMapping { GLVertexAttrib* attrib; MeshBufferType buf_type; }; struct ShaderProgram { GLuint prog_id; u32 num_blocks; GLUniformBlock* uniform_blocks; u32 num_uniforms; GLUniform* uniforms; u32 num_vertex_attribs; GLVertexAttrib* vertex_attribs; GLBufferToAttribMapping* attrib_mappings; char* name; u64 hash; // NOTE: hash of vs filpath + fs filepath concat }; struct GLBuffer { GLuint id; GLenum target; GLenum data_type; GLuint data_size; // NOTE: size of buffer in bytes GLint location; // NOTE: if used as backing for vertex attribute GLint binding_idx; // NOTE: if used as backing from uniform buffer object char* name; }; struct GLTexture { GLuint id; GLenum pixel_format; // NOTE: GL_RGB or GL_RGBA u32 width; u32 height; u64 filepath_hash; }; struct GLContext { GLuint binding_count; GLint max_binding_points; GLint max_vertex_blocks; GLint max_fragment_blocks; GLint max_ublock_size; GLint max_vertex_attribs; u32 max_ubos; u32 num_ubos; GLBuffer* uniform_buffers; u32 max_shaders; u32 num_shaders; ShaderProgram* shaders; u32 max_textures; u32 num_textures; GLTexture* textures; }; struct GLMesh { u32 num_indices; GLuint vao_id; bool has_texture; GLuint tex_id; mat4* node_xform; u32 num_vertex_attrib_buffers; GLBuffer* vertex_attrib_buffers; GLBuffer* element_buf; }; struct Animation; GLContext* initGLContext(MemoryArena* arena, u32 max_shaders, u32 max_textures, u32 max_ubos); // TODO: add more notes here describing the internals? This is the entry point // to a complex process of programatically assigning properties to our notion // of what a shader needs ie) uniforms, buffer block bindings, etc // NOTE: every shader program is assumed to have one uniform block named // "matrices" that contains the projection and view matrices, and one uniform // named "node_xform" for the node matrix bool addShaderProgram(MemoryArena* arena, GLContext* gl_ctx, const char* vs, const char* fs, const char* name); ShaderProgram* getShaderByName(const char* name, GLContext* gl_ctx); ShaderProgram* getShaderByID(GLContext* gl_ctx, GLuint prog_id); ShaderProgram* getShaderByHash(GLContext* gl_ctx, u64 hash); ShaderProgram* getFreeShader(GLContext* gl_ctx); GLBuffer* getFreeUBO(GLContext* gl_ctx); GLBuffer* getUBOByName(GLContext* gl_ctx, const char* name); GLTexture* getGLTexture(GLContext* gl_ctx, Texture* diffuse_img); GLBuffer* initGLBackingBuffer(GLContext* gl_ctx, MemoryArena* arena, const char* name, GLenum data_type, u32 buf_size, void* data); void updateGLBuffer(GLBuffer* gl_buf, void* data); void renderVAO(GLMesh* glmesh, mat4* node_xform, ShaderProgram* shader, GLTexture* gl_tex, GLenum draw_mode); GLVertexAttrib* getVertexAttribByName(ShaderProgram* shader, const char* name); GLMesh loadGLMesh(MemoryArena* arena, const Mesh& m, GLenum draw_mode, GLenum usage, GLTexture* diffuse_texture, u32 num_mappings, GLBufferToAttribMapping mappings[]);