2025-05-31 00:27:25 +02:00

121 lines
4.4 KiB
C

#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);
}