#include "render_impl.h" typedef struct s_gbuffer{ //framebuffer unsigned int framebuffer; unsigned int depthRenderbuffer; //texture unsigned int positionTexture; unsigned int normalTexture; unsigned int albedoSpecTexture; unsigned int zTexture; //format unsigned int width; unsigned int height; } gbuffer_t; gbuffer_t haven_gbuffer_init(int width, int height) { gbuffer_t buffer = {0}; buffer.height = height; buffer.width = width; buffer.framebuffer = rlLoadFramebuffer(); if (!buffer.framebuffer) { TraceLog(LOG_WARNING, "failed to create framebuffer"); exit(1); } rlEnableFramebuffer(buffer.framebuffer); buffer.positionTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); buffer.normalTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); buffer.albedoSpecTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); buffer.zTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); buffer.depthRenderbuffer = rlLoadTextureDepth(width, height, true); rlActiveDrawBuffers(4); rlFramebufferAttach(buffer.framebuffer, buffer.positionTexture, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(buffer.framebuffer, buffer.normalTexture, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(buffer.framebuffer, buffer.albedoSpecTexture, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(buffer.framebuffer, buffer.zTexture, RL_ATTACHMENT_COLOR_CHANNEL3, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(buffer.framebuffer, buffer.depthRenderbuffer, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); if (!rlFramebufferComplete(buffer.framebuffer)) { TraceLog(LOG_WARNING, "Framebuffer is not complete"); exit(1); } return (buffer); } void haven_deferred_set_loc(Shader shader) { rlEnableShader(shader.id); int tex_unit_posistion = 0; int tex_unit_normal = 1; int tex_unit_albedospec = 2; int tex_unit_z = 3; SetShaderValue(shader, rlGetLocationUniform(shader.id, "gPosition"), &tex_unit_posistion, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(shader, rlGetLocationUniform(shader.id, "gNormal"), &tex_unit_normal, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(shader, rlGetLocationUniform(shader.id, "gAlbedoSpec"), &tex_unit_albedospec, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(shader, rlGetLocationUniform(shader.id, "gZ"), &tex_unit_z, RL_SHADER_UNIFORM_SAMPLER2D); rlDisableShader(); } void haven_gbuffer_start_draw(const gbuffer_t gbuffer, const Camera3D camera, const Shader gbuffershader) { rlEnableFramebuffer(gbuffer.framebuffer); rlClearColor(0, 0, 0, 0); rlClearScreenBuffers(); rlDisableColorBlend(); BeginMode3D(camera); rlEnableShader(gbuffershader.id); } void haven_gbuffer_end_draw() { rlDisableShader(); EndMode3D(); rlEnableColorBlend(); rlDisableFramebuffer(); rlClearScreenBuffers(); } void haven_gbuffer_rendering(const gbuffer_t gbuffer, const Camera3D camera, const Shader deferredshader) { BeginMode3D(camera); { rlDisableColorBlend(); rlEnableShader(deferredshader.id); { // Bind our g-buffer textures // We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`, // `gAlbedoSpec` and gZ rlActiveTextureSlot(0); rlEnableTexture(gbuffer.positionTexture); rlActiveTextureSlot(1); rlEnableTexture(gbuffer.normalTexture); rlActiveTextureSlot(2); rlEnableTexture(gbuffer.albedoSpecTexture); rlActiveTextureSlot(3); rlEnableTexture(gbuffer.zTexture); // Finally, we draw a fullscreen quad to our default framebuffer // This will now be shaded using our deferred shader rlLoadDrawQuad(); } rlDisableShader(); rlEnableColorBlend(); } EndMode3D(); // As a last step, we now copy over the depth buffer from our g-buffer to the default framebuffer. rlBindFramebuffer(RL_READ_FRAMEBUFFER, gbuffer.framebuffer); rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0); rlBlitFramebuffer(0, 0, gbuffer.width, gbuffer.height, 0, 0, gbuffer.width, gbuffer.height, 0x00000100);//0x00000100 -> GL_DEPTH_BUFFER_BIT rlDisableFramebuffer(); } void haven_gbuffer_texture_render(const unsigned int texture_id, const unsigned int width, const unsigned int height) { DrawTextureRec((Texture2D){ .id = texture_id, .width = width, .height = -height, }, (Rectangle) {0, 0, width, -height}, Vector2Zero(), RAYWHITE); }