#pragma once #include #include #include #include "types.h" #include "util.h" 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; GLenum data_type; GLint data_size; GLint num_elements; char* name; }; struct GLUniformBlock { GLuint block_id; GLint binding_idx; 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; }; struct GLBufferToAttribMapping { GLVertexAttrib* attrib; MeshBufferType buf_type; }; struct ShaderProgram { GLuint prog_id; GLuint xforms_ubo_id; GLuint node_xform_id; GLint sampler_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 location; // NOTE: if used as backing for vertex attribute GLuint 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; }; // TODO: rename to GLMesh struct GLmesh { u32 num_indices; GLuint vao_id; GLuint tex_id; GLenum draw_mode; // NOTE: GL_LINES, GL_TRIANGLES GLenum usage; // NOTE: GL_STATIC_DRAW, GL_DYNAMIC_DRAW glm::mat4* node_xform; u32 num_vertex_attrib_buffers; GLBuffer* vertex_attrib_buffers; GLBuffer* element_buf; }; struct Animation; struct PointLight { glm::vec3 position; glm::vec3 color; u32 intensity; }; struct Transforms { glm::mat4 view_xform; glm::mat4 proj_xform; glm::mat4 normal_xform; }; const float DEFAULT_FOV = 60.f; const float NEAR_CLIP_PLANE = 5.f; const float DEFAULT_ASPECT_RATIO = 16.f / 9.f; const glm::vec3 DEFAULT_CAM_POS = { 0, 0, 30.f }; const glm::vec3 DEFAULT_LOOK_POS = { 0, 0, 0 }; // 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); GLTexture* getGLTexture(GLContext* gl_ctx, Texture* diffuse_img); void renderVAO(GLmesh* glmesh, glm::mat4* node_xform, ShaderProgram* shader, GLuint tex_id = 0); GLVertexAttrib* getVertexAttribByName(ShaderProgram* shader, const char* name); GLmesh loadGLMesh(const Mesh& m, GLenum draw_mode, GLuint diffuse_texture_id, u32 num_mappings, GLBufferToAttribMapping mappings[]); void initTransforms(MemoryArena* arena, Transforms* xforms, GLBuffer* xform_ubo, GLContext* gl_ctx, float fov = DEFAULT_FOV, float near_clip_plane = NEAR_CLIP_PLANE, float aspect_ratio = DEFAULT_ASPECT_RATIO, glm::vec3 cam_pos = DEFAULT_CAM_POS, glm::vec3 look_pos = DEFAULT_LOOK_POS);