vn/code/opengl_render.cpp

811 lines
24 KiB
C++
Raw Normal View History

2023-06-17 17:00:55 +00:00
// sixten: Functions implemented by the platform layer
static void *OpenGL_AllocateMemory(umm Size);
inline void *OpenGL_LoadFunction(char *Name);
static void OpenGL_DeallocateMemory(void *Memory);
//- sixten: OpenGL Render Layer
static void OpenGL_DebugMessageCallback(GLenum Source, GLenum Type, GLuint ID, GLenum Severity,
GLsizei Length, const GLchar *Message, const void *UserParam)
{
2023-12-23 07:27:22 +00:00
if(Severity == GL_DEBUG_SEVERITY_HIGH)
{
__debugbreak();
}
2023-06-17 17:00:55 +00:00
}
2023-12-23 07:27:22 +00:00
inline render_handle OpenGL_HandleFromTexture(opengl_texture Texture)
2023-06-17 17:00:55 +00:00
{
2023-12-23 07:27:22 +00:00
render_handle Result = {};
Result.U32[0] = Texture.ID;
Result.U32[1] = Texture.Format;
Result.U32[2] = Texture.Dim.x;
Result.U32[3] = Texture.Dim.y;
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-12-23 07:27:22 +00:00
inline opengl_texture OpenGL_TextureFromHandle(render_handle Handle)
2023-06-17 17:00:55 +00:00
{
2023-12-23 07:27:22 +00:00
opengl_texture Result = {};
Result.ID = Handle.U32[0];
Result.Format = (render_texture_format)Handle.U32[1];
Result.Dim.x = Handle.U32[2];
Result.Dim.y = Handle.U32[3];
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-12-23 07:27:22 +00:00
inline u32 OpenGL_InternalFormatFromTextureFormat(render_texture_format Format)
2023-06-17 17:00:55 +00:00
{
2023-12-23 07:27:22 +00:00
u32 InternalFormat = GL_INVALID_ENUM;
if(Format == Render_TextureFormat_R8)
{
InternalFormat = GL_RED;
}
else if(Format == Render_TextureFormat_RGB8)
{
InternalFormat = GL_RGB;
}
else if(Format == Render_TextureFormat_RGBA8)
{
InternalFormat = GL_RGBA;
}
else
{
InvalidCodepath;
}
return(InternalFormat);
2023-06-17 17:00:55 +00:00
}
global GLint Global_OpenGL_SwizzleMaskR8[4] = {GL_ONE, GL_ONE, GL_ONE, GL_RED};
global GLint Global_OpenGL_SwizzleMaskRGB8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ONE};
global GLint Global_OpenGL_SwizzleMaskRGBA8[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
2023-12-23 07:27:22 +00:00
inline GLint *OpenGL_SwizzleFromTextureFormat(render_texture_format Format)
2023-06-17 17:00:55 +00:00
{
2023-12-23 07:27:22 +00:00
GLint *Swizzle = 0;
if(Format == Render_TextureFormat_R8)
{
Swizzle = Global_OpenGL_SwizzleMaskR8;
}
else if(Format == Render_TextureFormat_RGB8)
{
Swizzle = Global_OpenGL_SwizzleMaskRGB8;
}
else if(Format == Render_TextureFormat_RGBA8)
{
Swizzle = Global_OpenGL_SwizzleMaskRGBA8;
}
else
{
InvalidCodepath;
}
return(Swizzle);
2023-06-17 17:00:55 +00:00
}
static RENDER_ALLOCATE_TEXTURE(OpenGL_AllocateTexture)
{
2023-12-23 07:27:22 +00:00
opengl_texture Texture = {};
Texture.Dim = Dim;
Texture.Format = Format;
glGenTextures(1, &Texture.ID);
Assert(Texture.ID);
u32 InternalFormat = OpenGL_InternalFormatFromTextureFormat(Format);
GLint *SwizzleMask = OpenGL_SwizzleFromTextureFormat(Format);
glBindTexture(GL_TEXTURE_2D, Texture.ID);
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Dim.x, Dim.y, 0, InternalFormat, GL_UNSIGNED_BYTE, Data);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, SwizzleMask);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(GenerateMipmap)
{
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
render_handle Handle = OpenGL_HandleFromTexture(Texture);
return(Handle);
}
RENDER_DEALLOCATE_TEXTURE(OpenGL_DeallocateTexture)
{
opengl_texture Texture = OpenGL_TextureFromHandle(Handle);
glDeleteTextures(1, &Texture.ID);
2023-06-17 17:00:55 +00:00
}
static RENDER_FILL_REGION(OpenGL_FillRegion)
{
2023-12-23 07:27:22 +00:00
opengl_texture Texture = OpenGL_TextureFromHandle(Handle);
glBindTexture(GL_TEXTURE_2D, Texture.ID);
glTexSubImage2D(GL_TEXTURE_2D, 0,
DestP.x, DestP.y, DestDim.x, DestDim.y,
OpenGL_InternalFormatFromTextureFormat(Texture.Format),
GL_UNSIGNED_BYTE, Data);
glBindTexture(GL_TEXTURE_2D, 0);
2023-06-17 17:00:55 +00:00
}
global char *OpenGL_ShaderHeader =
R"GLSL(
#version 330 core
#define s32 int
#define u32 uint
#define v2s ivec2
#define v2u uvec2
#define r32 float
#define v2 vec2
#define v3 vec3
#define v4 vec4
#define m4x4 mat4x4
#define V2 vec2
#define V3 vec3
#define V4 vec4
#define Min(a, b) min(a, b)
#define Max(a, b) max(a, b)
#define Clamp(x, min, max), clamp(x, min, max)
#define Clamp01(x), Clamp(x, 0, 1)
#define LinearBlend(A, B, C) mix(A, B, C)
#define AbsoluteValue(x) abs(x)
#define Length(x) length(x)
#define Pow(x, y) pow(x, y)
)GLSL";
static u32 OpenGL_CompileShaderProgram(char *VertexSource, char *FragmentSource)
{
2023-12-23 07:27:22 +00:00
u32 Result = 0;
u32 VertexShader = glCreateShader(GL_VERTEX_SHADER);
char *VertexSources[] =
{
OpenGL_ShaderHeader,
VertexSource
};
glShaderSource(VertexShader, ArrayCount(VertexSources), VertexSources, 0);
glCompileShader(VertexShader);
s32 VertexCompilationStatus;
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &VertexCompilationStatus);
if(VertexCompilationStatus)
{
u32 FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
char *FragmentSources[] =
{
OpenGL_ShaderHeader,
FragmentSource
};
glShaderSource(FragmentShader, ArrayCount(FragmentSources), FragmentSources, 0);
glCompileShader(FragmentShader);
s32 FragmentCompilationStatus;
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &FragmentCompilationStatus);
if(FragmentCompilationStatus)
{
u32 Program = glCreateProgram();
glAttachShader(Program, VertexShader);
glAttachShader(Program, FragmentShader);
glLinkProgram(Program);
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
s32 ProgramLinkStatus;
glGetProgramiv(Program, GL_LINK_STATUS, &ProgramLinkStatus);
if(ProgramLinkStatus)
{
Result = Program;
}
else
{
char InfoLog[1024];
glGetProgramInfoLog(Program, ArrayCount(InfoLog), 0, InfoLog);
InvalidCodepath;
}
}
else
{
char InfoLog[1024];
glGetShaderInfoLog(FragmentShader, ArrayCount(InfoLog), 0, InfoLog);
InvalidCodepath;
}
}
else
{
char InfoLog[1024];
glGetShaderInfoLog(VertexShader, ArrayCount(InfoLog), 0, InfoLog);
InvalidCodepath;
}
return(Result);
2023-06-17 17:00:55 +00:00
}
static quad_program OpenGL_CompileQuadProgram(void)
{
2023-12-23 07:27:22 +00:00
char *VertexSource =
R"GLSL(
2023-06-17 17:00:55 +00:00
in v2 In_P;
2023-12-23 07:27:22 +00:00
in v2 In_SourceP;
2023-06-17 17:00:55 +00:00
in s32 In_TextureIndex;
2023-12-23 07:27:22 +00:00
in u32 In_Color;
2023-06-17 17:00:55 +00:00
in v2 In_ToCenter;
in v2 In_HalfSize;
2023-12-23 07:27:22 +00:00
in r32 In_CornerRadius;
in r32 In_EdgeSoftness;
in r32 In_BorderThickness;
2023-06-17 17:00:55 +00:00
)GLSL"
2023-12-23 07:27:22 +00:00
"uniform sampler2D TextureSamplers[" Stringify(MAX_BOUND_TEXTURES) "];"
R"GLSL(
uniform v2 Uniform_Resolution;
2023-06-17 17:00:55 +00:00
flat out s32 TextureIndex;
2023-12-23 07:27:22 +00:00
out v2 DestP;
out v2 DestHalfSize;
out v2 DestCenter;
out v2 SourceP;
out v4 Color;
out r32 CornerRadius;
out r32 EdgeSoftness;
out r32 BorderThickness;
void main()
{
DestP = In_P;
DestCenter = In_P + In_ToCenter;
DestHalfSize = In_HalfSize;
SourceP = In_SourceP;
v2 ScreenP = DestP / Uniform_Resolution;;
ScreenP = ScreenP*2 - 1;
ScreenP.y = -ScreenP.y;
gl_Position = V4(ScreenP, 0, 1);
Color.r = r32((In_Color >> 24) & 255u)/255.0;
Color.g = r32((In_Color >> 16) & 255u)/255.0;
Color.b = r32((In_Color >> 8) & 255u)/255.0;
Color.a = r32((In_Color >> 0) & 255u)/255.0;
2023-06-17 17:00:55 +00:00
TextureIndex = In_TextureIndex;
2023-12-23 07:27:22 +00:00
CornerRadius = In_CornerRadius;
EdgeSoftness = In_EdgeSoftness;
BorderThickness = In_BorderThickness;
})GLSL";
char *FragmentSource =
R"GLSL(
flat in s32 TextureIndex;
in v2 DestP;
in v2 DestHalfSize;
in v2 DestCenter;
2023-06-17 17:00:55 +00:00
in v2 SourceP;
in v4 Color;
2023-12-23 07:27:22 +00:00
in r32 CornerRadius;
in r32 EdgeSoftness;
in r32 BorderThickness;
2023-06-17 17:00:55 +00:00
)GLSL"
2023-12-23 07:27:22 +00:00
"uniform sampler2D TextureSamplers[" Stringify(MAX_BOUND_TEXTURES) "];"
R"GLSL(
2023-06-17 17:00:55 +00:00
out v4 Out_Color;
2023-12-23 07:27:22 +00:00
2023-06-17 17:00:55 +00:00
r32 RoundedRect(v2 P, v2 Center, v2 HalfSize, r32 r)
{
v2 d2 = AbsoluteValue(Center - P) - HalfSize + r;
r32 Result = Min(Max(d2.x, d2.y), 0) + Length(Max(d2, 0)) - r;
return(Result);
}
void main()
{
r32 SoftnessPadding = Max(0, EdgeSoftness*2-1);
r32 Dist = RoundedRect(DestP, DestCenter, DestHalfSize - SoftnessPadding, CornerRadius);
r32 SDFFactor = 1 - smoothstep(0, 2*EdgeSoftness, Dist);
r32 BorderFactor = 1;
if(BorderThickness != 0)
{
v2 InteriorHalfSize = DestHalfSize - BorderThickness;
r32 InteriorRadiusReduce = Min(InteriorHalfSize.x / DestHalfSize.x, InteriorHalfSize.y / DestHalfSize.y);
r32 InteriorCornerRadius = CornerRadius*InteriorRadiusReduce*InteriorRadiusReduce;
r32 InsideDist = RoundedRect(DestP, DestCenter, InteriorHalfSize - SoftnessPadding, InteriorCornerRadius);
BorderFactor = smoothstep(0, 2*EdgeSoftness, InsideDist);
}
v4 TextureFactor = texture(TextureSamplers[TextureIndex], SourceP);
Out_Color = Color*TextureFactor*BorderFactor*SDFFactor;
})GLSL";
2023-12-23 07:27:22 +00:00
quad_program Program = {};
Program.ID = OpenGL_CompileShaderProgram(VertexSource, FragmentSource);
Program.PID = glGetAttribLocation(Program.ID, "In_P");
Program.SourcePID = glGetAttribLocation(Program.ID, "In_SourceP");
Program.TextureIndexID = glGetAttribLocation(Program.ID, "In_TextureIndex");
Program.ColorID = glGetAttribLocation(Program.ID, "In_Color");
Program.ToCenterID = glGetAttribLocation(Program.ID, "In_ToCenter");
Program.HalfSizeID = glGetAttribLocation(Program.ID, "In_HalfSize");
Program.CornerRadiusID = glGetAttribLocation(Program.ID, "In_CornerRadius");
Program.EdgeSoftnessID = glGetAttribLocation(Program.ID, "In_EdgeSoftness");
Program.BorderThicknessID = glGetAttribLocation(Program.ID, "In_BorderThickness");
glUseProgram(Program.ID);
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
temp Scratch = GetScratch(0, 0);
for(s32 TextureIndex = 0;
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
{
string Name = PushFormat(Scratch.Arena, "TextureSamplers[%i]", TextureIndex);
s32 Location = glGetUniformLocation(Program.ID, (char *)Name.Data);
glUniform1i(Location, TextureIndex);
}
ReleaseScratch(Scratch);
glUseProgram(0);
return(Program);
2023-06-17 17:00:55 +00:00
}
2023-08-22 03:19:51 +00:00
static instanced_quad_program OpenGL_CompileInstacedQuadProgram(void)
{
2023-12-23 07:27:22 +00:00
char *VertexSource =
R"GLSL(
2023-08-22 03:19:51 +00:00
2023-12-23 07:27:22 +00:00
in v4 In_Dest;
2023-08-22 03:19:51 +00:00
in v4 In_Source;
in s32 In_TextureIndex;
2023-12-23 07:27:22 +00:00
in u32 In_Color[4];
in r32 In_CornerRadius;
in r32 In_EdgeSoftness;
in r32 In_BorderThickness;
2023-08-22 03:19:51 +00:00
)GLSL"
2023-12-23 07:27:22 +00:00
"uniform sampler2D TextureSamplers[" Stringify(MAX_BOUND_TEXTURES) "];"
R"GLSL(
2023-08-22 03:19:51 +00:00
uniform v2 Uniform_Resolution;
out v2 DestP;
out v2 DestHalfSize;
out v2 DestCenter;
out v2 SourceP;
out v4 Color;
out r32 CornerRadius;
out r32 EdgeSoftness;
out r32 BorderThickness;
flat out s32 TextureIndex;
void main()
{
v2[] Vertices = V2[](V2(0, 0), V2(0, 1), V2(1, 0), V2(1, 1));
2023-09-05 17:50:49 +00:00
DestP = LinearBlend(In_Dest.xy, In_Dest.zw, Vertices[gl_VertexID]);
2023-08-22 03:19:51 +00:00
DestHalfSize = (In_Dest.zw-In_Dest.xy)/2;
DestCenter = (In_Dest.xy+In_Dest.zw)/2;
2023-09-05 17:50:49 +00:00
SourceP = LinearBlend(In_Source.xy, In_Source.zw, Vertices[gl_VertexID]);
2023-08-22 03:19:51 +00:00
v2 ScreenP = V2(DestP.x / Uniform_Resolution.x, DestP.y / Uniform_Resolution.y);
ScreenP = ScreenP*2 - 1;
2023-12-23 07:27:22 +00:00
ScreenP.y = -ScreenP.y;
2023-08-22 03:19:51 +00:00
gl_Position = V4(ScreenP, 0, 1);
u32 ColorData = In_Color[gl_VertexID];
Color.r = r32((ColorData >> 24) & 255u)/255.0;
2023-12-23 07:27:22 +00:00
Color.g = r32((ColorData >> 16) & 255u)/255.0;
Color.b = r32((ColorData >> 8) & 255u)/255.0;
Color.a = r32((ColorData >> 0) & 255u)/255.0;
2023-08-22 03:19:51 +00:00
CornerRadius = In_CornerRadius;
2023-12-23 07:27:22 +00:00
EdgeSoftness = In_EdgeSoftness;
BorderThickness = In_BorderThickness;
2023-08-22 03:19:51 +00:00
TextureIndex = In_TextureIndex;
}
)GLSL";
2023-12-23 07:27:22 +00:00
char *FragmentSource =
R"GLSL(
2023-08-22 03:19:51 +00:00
2023-12-23 07:27:22 +00:00
in v2 DestP;
in v2 DestHalfSize;
in v2 DestCenter;
2023-08-22 03:19:51 +00:00
in v2 SourceP;
in v4 Color;
2023-12-23 07:27:22 +00:00
in r32 CornerRadius;
in r32 EdgeSoftness;
in r32 BorderThickness;
2023-08-22 03:19:51 +00:00
flat in s32 TextureIndex;
)GLSL"
2023-12-23 07:27:22 +00:00
"uniform sampler2D TextureSamplers[" Stringify(MAX_BOUND_TEXTURES) "];"
R"GLSL(
2023-08-22 03:19:51 +00:00
out v4 Out_Color;
r32 RoundedRect(v2 P, v2 Center, v2 HalfSize, r32 r)
{
v2 d2 = AbsoluteValue(Center - P) - HalfSize + r;
r32 Result = Min(Max(d2.x, d2.y), 0) + Length(Max(d2, 0)) - r;
return(Result);
}
void main()
{
r32 SoftnessPadding = Max(0, EdgeSoftness*2-1);
r32 Dist = RoundedRect(DestP, DestCenter, DestHalfSize - SoftnessPadding, CornerRadius);
r32 SDFFactor = 1 - smoothstep(0, 2*EdgeSoftness, Dist);
r32 BorderFactor = 1;
if(BorderThickness != 0)
{
v2 InteriorHalfSize = DestHalfSize - BorderThickness;
2023-09-05 17:50:49 +00:00
v2 InteriorRadiusReducePair = InteriorHalfSize / DestHalfSize;
2023-08-22 03:19:51 +00:00
2023-09-05 17:50:49 +00:00
r32 InteriorRadiusReduce = Min(InteriorRadiusReducePair.x, InteriorRadiusReducePair.y);
2023-08-22 03:19:51 +00:00
r32 InteriorCornerRadius = CornerRadius*InteriorRadiusReduce*InteriorRadiusReduce;
r32 InsideDist = RoundedRect(DestP, DestCenter, InteriorHalfSize - SoftnessPadding, InteriorCornerRadius);
BorderFactor = smoothstep(0, 2*EdgeSoftness, InsideDist);
}
v4 TextureFactor = texture(TextureSamplers[TextureIndex], SourceP);
Out_Color = Color*SDFFactor*BorderFactor*TextureFactor;
}
)GLSL";
2023-12-23 07:27:22 +00:00
instanced_quad_program Program = {};
Program.ID = OpenGL_CompileShaderProgram(VertexSource, FragmentSource);
Program.DestID = glGetAttribLocation(Program.ID, "In_Dest");
Program.SourceID = glGetAttribLocation(Program.ID, "In_Source");
Program.TextureIndexID = glGetAttribLocation(Program.ID, "In_TextureIndex");
Program.ColorID[0] = glGetAttribLocation(Program.ID, "In_Color[0]");
Program.ColorID[1] = glGetAttribLocation(Program.ID, "In_Color[1]");
Program.ColorID[2] = glGetAttribLocation(Program.ID, "In_Color[2]");
Program.ColorID[3] = glGetAttribLocation(Program.ID, "In_Color[3]");
Program.CornerRadiusID = glGetAttribLocation(Program.ID, "In_CornerRadius");
Program.EdgeSoftnessID = glGetAttribLocation(Program.ID, "In_EdgeSoftness");
Program.BorderThicknessID = glGetAttribLocation(Program.ID, "In_BorderThickness");
glUseProgram(Program.ID);
Program.UniformResolutionLocation = glGetUniformLocation(Program.ID, "Uniform_Resolution");
temp Scratch = GetScratch(0, 0);
for(s32 TextureIndex = 0;
TextureIndex < MAX_BOUND_TEXTURES;
++TextureIndex)
{
string Name = PushFormat(Scratch.Arena, "TextureSamplers[%i]", TextureIndex);
s32 Location = glGetUniformLocation(Program.ID, (char *)Name.Data);
glUniform1i(Location, TextureIndex);
}
ReleaseScratch(Scratch);
glUseProgram(0);
return(Program);
2023-08-22 03:19:51 +00:00
}
2023-06-17 17:00:55 +00:00
#define OpenGL_EnableFloatVertexAttribute(Index, Size, Type, type, Member)\
if(Index != -1)\
{\
glEnableVertexAttribArray(Index);\
glVertexAttribPointer(Index, Size, Type, GL_FALSE, sizeof(type), (void *)OffsetOf(type, Member));\
2023-08-22 03:19:51 +00:00
if(VN_USE_INSTANCING)\
{\
glVertexAttribDivisor(Index, 1);\
}\
2023-06-17 17:00:55 +00:00
}
#define OpenGL_EnableIntegerVertexAttribute(Index, Size, Type, type, Member)\
if(Index != -1)\
{\
glEnableVertexAttribArray(Index);\
glVertexAttribIPointer(Index, Size, Type, sizeof(type), (void *)OffsetOf(type, Member));\
2023-08-22 03:19:51 +00:00
if(VN_USE_INSTANCING)\
{\
glVertexAttribDivisor(Index, 1);\
}\
2023-06-17 17:00:55 +00:00
}
#define OpenGL_DisableVertexAttribute(Index)\
if(Index != -1)\
{\
glDisableVertexAttribArray(Index);\
}
static void OpenGL_BeginProgram(quad_program *Program)
{
2023-12-23 07:27:22 +00:00
glUseProgram(Program->ID);
OpenGL_EnableFloatVertexAttribute(Program->PID, 2, GL_FLOAT, quad_vertex, P);
OpenGL_EnableFloatVertexAttribute(Program->SourcePID, 2, GL_FLOAT, quad_vertex, SourceP);
OpenGL_EnableIntegerVertexAttribute(Program->TextureIndexID, 1, GL_UNSIGNED_INT, quad_vertex, TextureIndex);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID, 1, GL_UNSIGNED_INT, quad_vertex, Color);
OpenGL_EnableFloatVertexAttribute(Program->ToCenterID, 2, GL_FLOAT, quad_vertex, ToCenter);
OpenGL_EnableFloatVertexAttribute(Program->HalfSizeID, 2, GL_FLOAT, quad_vertex, HalfSize);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID, 1, GL_FLOAT, quad_vertex, CornerRadius);
OpenGL_EnableFloatVertexAttribute(Program->EdgeSoftnessID, 1, GL_FLOAT, quad_vertex, EdgeSoftness);
OpenGL_EnableFloatVertexAttribute(Program->BorderThicknessID, 1, GL_FLOAT, quad_vertex, BorderThickness);
2023-06-17 17:00:55 +00:00
}
static void OpenGL_EndProgram(quad_program *Program)
{
2023-12-23 07:27:22 +00:00
OpenGL_DisableVertexAttribute(Program->PID);
OpenGL_DisableVertexAttribute(Program->SourcePID);
OpenGL_DisableVertexAttribute(Program->TextureIndexID);
OpenGL_DisableVertexAttribute(Program->ColorID);
OpenGL_DisableVertexAttribute(Program->ToCenterID);
OpenGL_DisableVertexAttribute(Program->HalfSizeID);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID);
OpenGL_DisableVertexAttribute(Program->EdgeSoftnessID);
OpenGL_DisableVertexAttribute(Program->BorderThicknessID);
glUseProgram(0);
2023-06-17 17:00:55 +00:00
}
2023-08-22 03:19:51 +00:00
static void OpenGL_BeginProgram(instanced_quad_program *Program)
{
2023-12-23 07:27:22 +00:00
glUseProgram(Program->ID);
OpenGL_EnableFloatVertexAttribute(Program->DestID, 4, GL_FLOAT, instanced_quad, Dest);
OpenGL_EnableFloatVertexAttribute(Program->SourceID, 4, GL_FLOAT, instanced_quad, Source);
OpenGL_EnableIntegerVertexAttribute(Program->TextureIndexID, 1, GL_UNSIGNED_INT, instanced_quad, TextureIndex);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[0], 1, GL_UNSIGNED_INT, instanced_quad, Color[0]);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[1], 1, GL_UNSIGNED_INT, instanced_quad, Color[1]);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[2], 1, GL_UNSIGNED_INT, instanced_quad, Color[2]);
OpenGL_EnableIntegerVertexAttribute(Program->ColorID[3], 1, GL_UNSIGNED_INT, instanced_quad, Color[3]);
OpenGL_EnableFloatVertexAttribute(Program->CornerRadiusID, 1, GL_FLOAT, instanced_quad, CornerRadius);
OpenGL_EnableFloatVertexAttribute(Program->EdgeSoftnessID, 1, GL_FLOAT, instanced_quad, EdgeSoftness);
OpenGL_EnableFloatVertexAttribute(Program->BorderThicknessID, 1, GL_FLOAT, instanced_quad, BorderThickness);
2023-08-22 03:19:51 +00:00
}
static void OpenGL_EndProgram(instanced_quad_program *Program)
{
2023-12-23 07:27:22 +00:00
OpenGL_DisableVertexAttribute(Program->DestID);
OpenGL_DisableVertexAttribute(Program->SourceID);
OpenGL_DisableVertexAttribute(Program->TextureIndexID);
OpenGL_DisableVertexAttribute(Program->ColorID[0]);
OpenGL_DisableVertexAttribute(Program->ColorID[1]);
OpenGL_DisableVertexAttribute(Program->ColorID[2]);
OpenGL_DisableVertexAttribute(Program->ColorID[3]);
OpenGL_DisableVertexAttribute(Program->CornerRadiusID);
OpenGL_DisableVertexAttribute(Program->EdgeSoftnessID);
OpenGL_DisableVertexAttribute(Program->BorderThicknessID);
glUseProgram(0);
2023-08-22 03:19:51 +00:00
}
2023-06-17 17:00:55 +00:00
static opengl_context OpenGL_SetupContext(vn_render_commands *RenderCommands, umm MaxPushBufferSize)
{
2023-12-23 07:27:22 +00:00
opengl_context Context = {};
RenderCommands->MaxPushBufferSize = MaxPushBufferSize;
RenderCommands->PushBufferBase = (u8 *)OpenGL_AllocateMemory(RenderCommands->MaxPushBufferSize);
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
RenderCommands->MaxInstancedQuadCount = MAX_QUAD_COUNT;
RenderCommands->InstancedQuadBase = (instanced_quad *)OpenGL_AllocateMemory(RenderCommands->MaxInstancedQuadCount*sizeof(instanced_quad));
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
RenderCommands->MaxQuadVertexCount = MAX_QUAD_COUNT*4;
RenderCommands->QuadVertexBase = (quad_vertex *)OpenGL_AllocateMemory(RenderCommands->MaxQuadVertexCount*sizeof(quad_vertex));
RenderCommands->MaxQuadIndexCount = MAX_QUAD_COUNT*6;
RenderCommands->QuadIndexBase = (s32 *)OpenGL_AllocateMemory(RenderCommands->MaxQuadIndexCount*sizeof(s32));
2023-07-19 15:09:41 +00:00
#endif
2023-12-23 07:27:22 +00:00
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
Context.InstancedQuadProgram = OpenGL_CompileInstacedQuadProgram();
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
Context.QuadProgram = OpenGL_CompileQuadProgram();
2023-08-22 03:19:51 +00:00
#endif
2023-12-23 07:27:22 +00:00
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
glGenBuffers(1, &Context.InstancedQuadBuffer);
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
glGenBuffers(1, &Context.VertexBuffer);
glGenBuffers(1, &Context.IndexBuffer);
2023-08-22 03:19:51 +00:00
#endif
2023-12-23 07:27:22 +00:00
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
glBindBuffer(GL_ARRAY_BUFFER, Context.InstancedQuadBuffer);
glBufferData(GL_ARRAY_BUFFER, RenderCommands->MaxInstancedQuadCount*sizeof(instanced_quad), 0, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
glBindBuffer(GL_ARRAY_BUFFER, Context.VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, RenderCommands->MaxQuadVertexCount*sizeof(quad_vertex), 0, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Context.IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, RenderCommands->MaxQuadIndexCount*sizeof(s32), 0, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2023-08-22 03:19:51 +00:00
#endif
2023-12-23 07:27:22 +00:00
u32 WhiteData = 0xFFFFFFFF;
RenderCommands->WhiteTexture = OpenGL_AllocateTexture(V2S32(1, 1), Render_TextureFormat_RGBA8, false, &WhiteData);
RenderCommands->AllocateTexture = OpenGL_AllocateTexture;
RenderCommands->DeallocateTexture = OpenGL_DeallocateTexture;
RenderCommands->FillRegion = OpenGL_FillRegion;
2023-08-22 03:19:51 +00:00
#if VN_SLOW&&0
2023-12-23 07:27:22 +00:00
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(OpenGL_DebugMessageCallback, 0);
2023-06-17 17:00:55 +00:00
#endif
2023-12-23 07:27:22 +00:00
u32 DummyVertexArray;
glGenVertexArrays(1, &DummyVertexArray);
glBindVertexArray(DummyVertexArray);
return(Context);
2023-06-17 17:00:55 +00:00
}
static void OpenGL_BeginFrame(vn_render_commands *RenderCommands, v2 RenderDim)
{
2023-12-23 07:27:22 +00:00
RenderCommands->PushBufferAt = RenderCommands->PushBufferBase;
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
RenderCommands->InstancedQuadCount = 0;
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
RenderCommands->QuadVertexCount = 0;
RenderCommands->QuadIndexCount = 0;
2023-07-19 15:09:41 +00:00
#endif
2023-12-23 07:27:22 +00:00
RenderCommands->RenderDim = RenderDim;
2023-06-17 17:00:55 +00:00
}
static void OpenGL_EndFrame(opengl_context *Context, vn_render_commands *RenderCommands)
{
2023-12-23 07:27:22 +00:00
glViewport(0, 0, RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
glScissor(0, 0, RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_SCISSOR_TEST);
2023-08-22 03:19:51 +00:00
#if !VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
glBindBuffer(GL_ARRAY_BUFFER, Context->VertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Context->IndexBuffer);
void *VertexData = RenderCommands->QuadVertexBase;
umm VertexSize = RenderCommands->QuadVertexCount*sizeof(quad_vertex);
glBufferSubData(GL_ARRAY_BUFFER, 0, VertexSize, VertexData);
void *IndexData = RenderCommands->QuadIndexBase;
umm IndexSize = RenderCommands->QuadIndexCount*sizeof(s32);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, IndexSize, IndexData);
2023-08-22 03:19:51 +00:00
#endif
2023-12-23 07:27:22 +00:00
for(u8 *PushBufferAt = RenderCommands->PushBufferBase;
PushBufferAt < RenderCommands->PushBufferAt;)
{
render_command_header *Header = (render_command_header *)PushBufferAt;
PushBufferAt += sizeof(*Header);
switch(Header->Type)
{
case Render_Command_render_command_clear:
{
render_command_clear *Command = (render_command_clear *)PushBufferAt;
PushBufferAt += sizeof(*Command);
glClearColor(Command->Color.r, Command->Color.g, Command->Color.b, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
} break;
2023-08-22 03:19:51 +00:00
#if VN_USE_INSTANCING
2023-12-23 07:27:22 +00:00
case Render_Command_render_command_instanced_quads:
{
render_command_instanced_quads *Command = (render_command_instanced_quads *)PushBufferAt;
PushBufferAt += sizeof(*Command);
render_texture_mapping *Mapping = &Command->Mapping;
for(s32 TextureIndex = 0;
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
{
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
glActiveTexture(GL_TEXTURE0 + TextureIndex);
glBindTexture(GL_TEXTURE_2D, Texture.ID);
}
glBindBuffer(GL_ARRAY_BUFFER, Context->InstancedQuadBuffer);
void *VertexData = RenderCommands->InstancedQuadBase+Command->QuadBufferIndex;
umm VertexSize = Command->QuadCount*sizeof(instanced_quad);
glBufferSubData(GL_ARRAY_BUFFER, 0, VertexSize, VertexData);
OpenGL_BeginProgram(&Context->InstancedQuadProgram);
glUniform2f(Context->InstancedQuadProgram.UniformResolutionLocation,
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, Command->QuadCount);
OpenGL_EndProgram(&Context->InstancedQuadProgram);
glBindTexture(GL_TEXTURE_2D, 0);
} break;
case Render_Command_render_command_clip:
{
render_command_clip *Command = (render_command_clip *)PushBufferAt;
PushBufferAt += sizeof(*Command);
v2_r32 P = Command->ClipRect.Min;
P.x = Max(Round(P.x), 0.0f);
P.y = Max(Round(P.y), 0.0f);
v2_r32 Dim = DimOfRange(Command->ClipRect);
Dim.x = Max(Round(Dim.x), 0.0f);
Dim.y = Max(Round(Dim.y), 0.0f);
v2_r32 FlippedP = V2R32(P.x, RenderCommands->RenderDim.y-Dim.y-P.y);
glScissor(FlippedP.x, FlippedP.y, Dim.x, Dim.y);
} break;
2023-08-22 03:19:51 +00:00
#else
2023-12-23 07:27:22 +00:00
case Render_Command_render_command_quads:
{
render_command_quads *Command = (render_command_quads *)PushBufferAt;
PushBufferAt += sizeof(*Command);
OpenGL_BeginProgram(&Context->QuadProgram);
glUniform2f(Context->QuadProgram.UniformResolutionLocation,
RenderCommands->RenderDim.x, RenderCommands->RenderDim.y);
render_texture_mapping *Mapping = &Command->Mapping;
for(s32 TextureIndex = 0;
TextureIndex < Mapping->TexturesUsed;
++TextureIndex)
{
opengl_texture Texture = OpenGL_TextureFromHandle(Mapping->Textures[TextureIndex]);
glActiveTexture(GL_TEXTURE0 + TextureIndex);
glBindTexture(GL_TEXTURE_2D, Texture.ID);
}
glDrawElements(GL_TRIANGLES, Command->QuadCount*6, GL_UNSIGNED_INT, 0);
OpenGL_EndProgram(&Context->QuadProgram);
glBindTexture(GL_TEXTURE_2D, 0);
} break;
2023-07-19 15:09:41 +00:00
#endif
2023-12-23 07:27:22 +00:00
InvalidDefaultCase;
}
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
2023-06-17 17:00:55 +00:00
}