wip: renderstate impl

main
Dominik Madarász 2024-04-11 00:19:08 +02:00
parent 87c37ae3ad
commit 1c19c44400
10 changed files with 924 additions and 195 deletions

View File

@ -1032,6 +1032,38 @@ typedef struct reflect_t {
const char* symbol_naked(const char *s);
int ui_reflect(const char *mask);
typedef unsigned handle;
typedef struct renderstate_t {
int viewportX;
int viewportY;
int viewportWidth;
int viewportHeight;
float clearColor[4];
double clearDepth;
bool depthTestEnabled;
unsigned depthFunc;
bool blendEnabled;
unsigned blendFunc;
unsigned blendSrc;
unsigned blendDst;
bool cullFaceEnabled;
unsigned cullFaceMode;
bool stencilTestEnabled;
unsigned stencilFunc;
int stencilRef;
unsigned stencilMask;
unsigned frontFace;
bool smoothLineEnabled;
float lineWidth;
bool pointSizeEnabled;
float pointSize;
unsigned polygonModeFace;
unsigned polygonModeMode;
bool scissorTestEnabled;
int scissorBox[4];
} renderstate_t;
renderstate_t renderstate();
bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB);
void renderstate_apply(const renderstate_t *state);
unsigned rgba( uint8_t r, uint8_t g, uint8_t b, uint8_t a );
unsigned bgra( uint8_t b, uint8_t g, uint8_t r, uint8_t a );
unsigned rgbaf( float r, float g, float b, float a );
@ -1148,6 +1180,7 @@ typedef struct shadowmap_t {
unsigned shader(const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
unsigned shader_bind(unsigned program);
int shader_uniform(const char *name);
void shader_bool(const char *uniform, bool i );
void shader_int(const char *uniform, int i);
void shader_uint(const char *uniform, unsigned i );
@ -1362,6 +1395,7 @@ typedef struct model_t {
float *instanced_matrices;
unsigned num_instances;
int stored_flags;
renderstate_t rs;
} model_t;
enum BILLBOARD_MODE {
BILLBOARD_X = 0x1,

View File

@ -0,0 +1,71 @@
#include <v4k.h>
int main() {
window_create(40, WINDOW_SQUARE | WINDOW_MSAA8);
window_title(__FILE__);
// set up pipeline
renderstate_t state = renderstate();
state.clearColor[0] = 0.2f;
state.clearColor[1] = 0.2f;
state.clearColor[2] = 0.2f;
state.clearColor[3] = 1.0f;
state.depthTestEnabled = GL_TRUE;
state.depthFunc = GL_LEQUAL;
state.blendEnabled = GL_FALSE;
state.cullFaceEnabled = GL_TRUE;
// prepare triangle buffer
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// basic shader
const char *vertex_shader_src = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main() {\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragment_shader_src = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
handle program = shader(vertex_shader_src, fragment_shader_src, "aPos", "FragColor", "");
// app loop
while( window_swap() ) {
// input controls
if( input(KEY_ESC) ) break;
// bind pipeline
renderstate_apply(&state);
// clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw triangle
glUseProgram(program);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}

View File

@ -17030,6 +17030,65 @@ API int ui_reflect(const char *mask); // *, model* or NULL
typedef unsigned handle; // GLuint
// -----------------------------------------------------------------------------
// renderstate
typedef struct renderstate_t {
// Viewport parameters
int viewportX;
int viewportY;
int viewportWidth;
int viewportHeight;
// Clear color
float clearColor[4];
// Clear depth
double clearDepth;
// Depth test
bool depthTestEnabled;
unsigned depthFunc;
// Blending
bool blendEnabled;
unsigned blendFunc;
unsigned blendSrc;
unsigned blendDst;
// Culling
bool cullFaceEnabled;
unsigned cullFaceMode;
// Stencil test
bool stencilTestEnabled;
unsigned stencilFunc;
int stencilRef;
unsigned stencilMask;
// Face culling direction
unsigned frontFace; // GL_CW or GL_CCW
// Line width
bool smoothLineEnabled;
float lineWidth;
// Point size
bool pointSizeEnabled;
float pointSize;
// Polygon mode
unsigned polygonModeFace;
unsigned polygonModeMode;
// Scissor test
bool scissorTestEnabled;
int scissorBox[4];
} renderstate_t;
API renderstate_t renderstate();
API bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB);
API void renderstate_apply(const renderstate_t *state);
// -----------------------------------------------------------------------------
// colors
@ -17250,6 +17309,7 @@ API void shadowmatrix_ortho(mat44 shm_proj, float left, float right, float botto
API unsigned shader(const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_bind(unsigned program);
API int shader_uniform(const char *name);
API void shader_bool(const char *uniform, bool i );
API void shader_int(const char *uniform, int i);
API void shader_uint(const char *uniform, unsigned i );
@ -17599,6 +17659,7 @@ typedef struct model_t {
unsigned num_instances;
int stored_flags;
renderstate_t rs;
} model_t;
enum BILLBOARD_MODE {
@ -363103,6 +363164,9 @@ typedef struct font_t {
// vbos
GLuint vbo_quad; // vec2: simply just a regular [0,1]x[0,1] quad
GLuint vbo_instances; // vec4: (char_pos_x, char_pos_y, char_index, color_index)
// render state
renderstate_t rs;
} font_t;
enum { FONTS_MAX = 10 };
@ -363441,6 +363505,16 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
glUniform2f(glGetUniformLocation(f->program, "res_meta"), f->num_glyphs, 2);
glUniform1f(glGetUniformLocation(f->program, "num_colors"), FONT_MAX_COLORS);
(void)flags;
// set up pipeline
f->rs = renderstate();
f->rs.blendEnabled = 1;
f->rs.blendFunc = GL_FUNC_ADD;
f->rs.blendSrc = GL_SRC_ALPHA;
f->rs.blendDst = GL_ONE_MINUS_SRC_ALPHA;
f->rs.scissorTestEnabled = 1;
f->rs.depthTestEnabled = 0;
f->rs.cullFaceEnabled = 0;
}
void font_face(const char *tag, const char *filename_ttf, float font_size, unsigned flags) {
@ -363471,25 +363545,10 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glGetIntegerv(GL_TEXTURE_BINDING_1D, &last_texture2);
glGetIntegerv(GL_BLEND_SRC, &last_blend_src);
glGetIntegerv(GL_BLEND_DST, &last_blend_dst);
glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// @fixme: store existing scissor test setup
glEnable(GL_SCISSOR_TEST);
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
glDisable(GL_DEPTH_TEST);
f->rs.scissorBox[0] = rect.x;
f->rs.scissorBox[1] = window_height() - (rect.y+rect.w);
f->rs.scissorBox[2] = rect.z;
f->rs.scissorBox[3] = rect.w;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, f->texture_fontdata);
@ -363515,6 +363574,9 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glBindBuffer(GL_ARRAY_BUFFER, f->vbo_instances);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4*4*glyph_idx, glyph_data);
// setup pipeline
renderstate_apply(&f->rs);
// actual drawing
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, glyph_idx);
@ -363528,13 +363590,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_1D, last_texture2);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBindVertexArray(last_vertex_array);
glBlendFunc(last_blend_src, last_blend_dst);
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
}
// 1. call font_face() if it's the first time it's called.
@ -370069,6 +370125,154 @@ void glCopyBackbufferToTexture( texture_t *tex ) { // unused
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 0, 0, window_width(), window_height(), 0 );
}
// ----------------------------------------------------------------------------
// renderstate
renderstate_t renderstate() {
renderstate_t state = {0};
// Set default viewport parameters
state.viewportX = 0;
state.viewportY = 0;
state.viewportWidth = window_width();
state.viewportHeight = window_height();
// Set default clear color to black
state.clearColor[0] = 0.0f; // Red
state.clearColor[1] = 0.0f; // Green
state.clearColor[2] = 0.0f; // Blue
state.clearColor[3] = 1.0f; // Alpha
// Set default clear depth to maximum distance
state.clearDepth = 1.0;
// Enable depth test by default with less or equal function
state.depthTestEnabled = GL_TRUE;
state.depthFunc = GL_LEQUAL;
// Disable blending by default
state.blendEnabled = GL_FALSE;
state.blendFunc = GL_FUNC_ADD;
state.blendSrc = GL_ONE;
state.blendDst = GL_ZERO;
// Enable culling by default and cull back faces
state.cullFaceEnabled = GL_TRUE;
state.cullFaceMode = GL_BACK;
// Disable stencil test by default
state.stencilTestEnabled = GL_FALSE;
state.stencilFunc = GL_ALWAYS;
state.stencilRef = 0;
state.stencilMask = 0xFFFFFFFF;
// Set default front face to counter-clockwise
state.frontFace = GL_CCW;
// Set default line width
state.smoothLineEnabled = GL_FALSE;
state.lineWidth = 1.0f;
// Set default point size
state.pointSizeEnabled = GL_FALSE;
state.pointSize = 1.0f;
// Set default polygon mode to fill
state.polygonModeFace = GL_FRONT_AND_BACK;
state.polygonModeMode = GL_FILL;
// Disable scissor test by default
state.scissorTestEnabled = GL_FALSE;
state.scissorBox[0] = 0;
state.scissorBox[1] = 0;
state.scissorBox[2] = window_width();
state.scissorBox[3] = window_height();
return state;
}
bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB) {
return memcmp(stateA, stateB, sizeof(renderstate_t)) == 0;
}
void renderstate_apply(const renderstate_t *state) {
if (state != NULL) {
// Apply viewport parameters
glViewport(state->viewportX, state->viewportY, state->viewportWidth, state->viewportHeight);
// Apply clear color
glClearColor(state->clearColor[0], state->clearColor[1], state->clearColor[2], state->clearColor[3]);
// Apply clear depth
glClearDepth(state->clearDepth);
// Apply depth test
if (state->depthTestEnabled) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(state->depthFunc);
} else {
glDisable(GL_DEPTH_TEST);
}
// Apply blending
if (state->blendEnabled) {
glEnable(GL_BLEND);
glBlendEquation(state->blendFunc);
glBlendFunc(state->blendSrc, state->blendDst);
} else {
glDisable(GL_BLEND);
}
// Apply culling @fixme
// if (state->cullFaceEnabled) {
// glEnable(GL_CULL_FACE);
// glCullFace(state->cullFaceMode);
// } else {
// glDisable(GL_CULL_FACE);
// }
// Apply stencil test
if (state->stencilTestEnabled) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(state->stencilFunc, state->stencilRef, state->stencilMask);
} else {
glDisable(GL_STENCIL_TEST);
}
// Apply front face direction @fixme
// glFrontFace(state->frontFace);
// Apply line width
glLineWidth(state->lineWidth);
// apply smooth lines
if (state->smoothLineEnabled) {
glEnable(GL_LINE_SMOOTH);
} else {
glDisable(GL_LINE_SMOOTH);
}
// Apply point size
if (state->pointSizeEnabled) {
glEnable(GL_PROGRAM_POINT_SIZE);
glPointSize(state->pointSize);
} else {
glDisable(GL_PROGRAM_POINT_SIZE);
}
// Apply polygon mode
glPolygonMode(state->polygonModeFace, state->polygonModeMode);
// Apply scissor test
if (state->scissorTestEnabled) {
glEnable(GL_SCISSOR_TEST);
glScissor(state->scissorBox[0], state->scissorBox[1], state->scissorBox[2], state->scissorBox[3]);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
}
// ----------------------------------------------------------------------------
// shaders
@ -370543,7 +370747,7 @@ typedef map(unsigned,int) uniform_binding;
static __thread unsigned last_shader = -1;
static __thread quarks_db uniform_names;
static __thread map(handle, uniform_binding) uniforms;
static
int shader_uniform(const char *name) {
do_once map_init(uniforms, less_int, hash_int);
if (!map_find(uniforms, last_shader)) {
@ -371873,17 +372077,21 @@ void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
API vec4 window_getcolor_(); // internal use, not public
static renderstate_t skybox_rs;
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
//glClear(GL_DEPTH_BUFFER_BIT);
//glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
do_once {
skybox_rs = renderstate();
}
// we have to reset clear color here, because of wrong alpha compositing issues on native transparent windows otherwise
vec4 bgcolor = window_getcolor_(); glClearColor(bgcolor.r, bgcolor.g, bgcolor.b, 1); // @transparent
vec4 bgcolor = window_getcolor_();
skybox_rs.clearColor[0] = bgcolor.r;
skybox_rs.clearColor[1] = bgcolor.g;
skybox_rs.clearColor[2] = bgcolor.b;
skybox_rs.clearColor[3] = 1; // @transparent
mat44 mvp; multiply44x2(mvp, proj, view);
@ -371893,6 +372101,8 @@ int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
if( sky->flags ) {
shader_cubemap("u_cubemap", sky->cubemap.id);
}
renderstate_apply(&skybox_rs);
return 0; // @fixme: return sortable hash here?
}
int skybox_pop_state() {
@ -371903,7 +372113,6 @@ int skybox_pop_state() {
}
int skybox_render(skybox_t *sky, mat44 proj, mat44 view) {
skybox_push_state(sky, proj, view);
glEnable(GL_DEPTH_TEST);
mesh_render(&sky->geometry);
skybox_pop_state();
return 0;
@ -373562,6 +373771,11 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model,
model_t model_from_mem(const void *mem, int len, int flags) {
model_t m = {0};
{
m.rs = renderstate();
m.rs.blendEnabled = 1;
}
m.stored_flags = flags;
m.shading = SHADING_PHONG;
@ -373845,6 +374059,8 @@ void model_draw_call(model_t m, int shader) {
handle old_shader = last_shader;
shader_bind(shader);
renderstate_apply(&m.rs);
glBindVertexArray( q->vao );
struct iqmtriangle *tris = NULL;
@ -374143,6 +374359,7 @@ typedef struct text2d_cmd {
float sca;
} text2d_cmd;
static renderstate_t dd_rs;
static uint32_t dd_color = ~0u;
static GLuint dd_program = -1;
static int dd_u_color = -1;
@ -374176,7 +374393,9 @@ void ddraw_flush() {
}
void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnable(GL_DEPTH_TEST);
do_once dd_rs = renderstate();
dd_rs.depthTestEnabled = 1;
glActiveTexture(GL_TEXTURE0);
mat44 mvp;
@ -374191,16 +374410,16 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnableVertexAttribArray(0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_PROGRAM_POINT_SIZE); // for GL_POINTS
glEnable(GL_LINE_SMOOTH); // for GL_LINES (thin)
dd_rs.pointSizeEnabled = 1;
dd_rs.smoothLineEnabled = 1;
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -374229,10 +374448,11 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp);
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -374251,9 +374471,6 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
array_resize(dd_text2d, 0);
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(0);
ddraw_color(WHITE); // reset color for next drawcall
@ -379529,7 +379746,20 @@ struct nk_glfw *window_handle_nkglfw() {
return g->nk_glfw;
}
static renderstate_t window_rs;
void glNewFrame() {
do_once {
window_rs = renderstate();
window_rs.blendEnabled = 1;
window_rs.depthTestEnabled = 1;
}
window_rs.clearColor[0] = winbgcolor.r;
window_rs.clearColor[1] = winbgcolor.g;
window_rs.clearColor[2] = winbgcolor.b;
window_rs.clearColor[3] = window_has_transparent() ? 0 : winbgcolor.a;
// @transparent debug
// if( input_down(KEY_F1) ) window_transparent(window_has_transparent()^1);
// if( input_down(KEY_F2) ) window_maximize(window_has_maximize()^1);
@ -379550,30 +379780,8 @@ void glNewFrame() {
g->width = w;
g->height = h;
// blending defaults
glEnable(GL_BLEND);
renderstate_apply(&window_rs);
// culling defaults
// glEnable(GL_CULL_FACE);
// glCullFace(GL_BACK);
// glFrontFace(GL_CCW);
// depth-testing defaults
glEnable(GL_DEPTH_TEST);
// glDepthFunc(GL_LESS);
// depth-writing defaults
// glDepthMask(GL_TRUE);
// seamless cubemaps
// glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glViewport(0, 0, window_width(), window_height());
// GLfloat bgColor[4]; glGetFloatv(GL_COLOR_CLEAR_VALUE, bgColor);
glClearColor(winbgcolor.r, winbgcolor.g, winbgcolor.b, window_has_transparent() ? 0 : winbgcolor.a); // @transparent
//glClearColor(0.15,0.15,0.15,1);
//glClearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
}

View File

@ -1554,6 +1554,9 @@ typedef struct font_t {
// vbos
GLuint vbo_quad; // vec2: simply just a regular [0,1]x[0,1] quad
GLuint vbo_instances; // vec4: (char_pos_x, char_pos_y, char_index, color_index)
// render state
renderstate_t rs;
} font_t;
enum { FONTS_MAX = 10 };
@ -1892,6 +1895,16 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
glUniform2f(glGetUniformLocation(f->program, "res_meta"), f->num_glyphs, 2);
glUniform1f(glGetUniformLocation(f->program, "num_colors"), FONT_MAX_COLORS);
(void)flags;
// set up pipeline
f->rs = renderstate();
f->rs.blendEnabled = 1;
f->rs.blendFunc = GL_FUNC_ADD;
f->rs.blendSrc = GL_SRC_ALPHA;
f->rs.blendDst = GL_ONE_MINUS_SRC_ALPHA;
f->rs.scissorTestEnabled = 1;
f->rs.depthTestEnabled = 0;
f->rs.cullFaceEnabled = 0;
}
void font_face(const char *tag, const char *filename_ttf, float font_size, unsigned flags) {
@ -1922,25 +1935,10 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glGetIntegerv(GL_TEXTURE_BINDING_1D, &last_texture2);
glGetIntegerv(GL_BLEND_SRC, &last_blend_src);
glGetIntegerv(GL_BLEND_DST, &last_blend_dst);
glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// @fixme: store existing scissor test setup
glEnable(GL_SCISSOR_TEST);
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
glDisable(GL_DEPTH_TEST);
f->rs.scissorBox[0] = rect.x;
f->rs.scissorBox[1] = window_height() - (rect.y+rect.w);
f->rs.scissorBox[2] = rect.z;
f->rs.scissorBox[3] = rect.w;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, f->texture_fontdata);
@ -1966,6 +1964,9 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glBindBuffer(GL_ARRAY_BUFFER, f->vbo_instances);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4*4*glyph_idx, glyph_data);
// setup pipeline
renderstate_apply(&f->rs);
// actual drawing
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, glyph_idx);
@ -1979,13 +1980,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_1D, last_texture2);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBindVertexArray(last_vertex_array);
glBlendFunc(last_blend_src, last_blend_dst);
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
}
// 1. call font_face() if it's the first time it's called.

View File

@ -50,6 +50,154 @@ void glCopyBackbufferToTexture( texture_t *tex ) { // unused
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 0, 0, window_width(), window_height(), 0 );
}
// ----------------------------------------------------------------------------
// renderstate
renderstate_t renderstate() {
renderstate_t state = {0};
// Set default viewport parameters
state.viewportX = 0;
state.viewportY = 0;
state.viewportWidth = window_width();
state.viewportHeight = window_height();
// Set default clear color to black
state.clearColor[0] = 0.0f; // Red
state.clearColor[1] = 0.0f; // Green
state.clearColor[2] = 0.0f; // Blue
state.clearColor[3] = 1.0f; // Alpha
// Set default clear depth to maximum distance
state.clearDepth = 1.0;
// Enable depth test by default with less or equal function
state.depthTestEnabled = GL_TRUE;
state.depthFunc = GL_LEQUAL;
// Disable blending by default
state.blendEnabled = GL_FALSE;
state.blendFunc = GL_FUNC_ADD;
state.blendSrc = GL_ONE;
state.blendDst = GL_ZERO;
// Enable culling by default and cull back faces
state.cullFaceEnabled = GL_TRUE;
state.cullFaceMode = GL_BACK;
// Disable stencil test by default
state.stencilTestEnabled = GL_FALSE;
state.stencilFunc = GL_ALWAYS;
state.stencilRef = 0;
state.stencilMask = 0xFFFFFFFF;
// Set default front face to counter-clockwise
state.frontFace = GL_CCW;
// Set default line width
state.smoothLineEnabled = GL_FALSE;
state.lineWidth = 1.0f;
// Set default point size
state.pointSizeEnabled = GL_FALSE;
state.pointSize = 1.0f;
// Set default polygon mode to fill
state.polygonModeFace = GL_FRONT_AND_BACK;
state.polygonModeMode = GL_FILL;
// Disable scissor test by default
state.scissorTestEnabled = GL_FALSE;
state.scissorBox[0] = 0;
state.scissorBox[1] = 0;
state.scissorBox[2] = window_width();
state.scissorBox[3] = window_height();
return state;
}
bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB) {
return memcmp(stateA, stateB, sizeof(renderstate_t)) == 0;
}
void renderstate_apply(const renderstate_t *state) {
if (state != NULL) {
// Apply viewport parameters
glViewport(state->viewportX, state->viewportY, state->viewportWidth, state->viewportHeight);
// Apply clear color
glClearColor(state->clearColor[0], state->clearColor[1], state->clearColor[2], state->clearColor[3]);
// Apply clear depth
glClearDepth(state->clearDepth);
// Apply depth test
if (state->depthTestEnabled) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(state->depthFunc);
} else {
glDisable(GL_DEPTH_TEST);
}
// Apply blending
if (state->blendEnabled) {
glEnable(GL_BLEND);
glBlendEquation(state->blendFunc);
glBlendFunc(state->blendSrc, state->blendDst);
} else {
glDisable(GL_BLEND);
}
// Apply culling @fixme
// if (state->cullFaceEnabled) {
// glEnable(GL_CULL_FACE);
// glCullFace(state->cullFaceMode);
// } else {
// glDisable(GL_CULL_FACE);
// }
// Apply stencil test
if (state->stencilTestEnabled) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(state->stencilFunc, state->stencilRef, state->stencilMask);
} else {
glDisable(GL_STENCIL_TEST);
}
// Apply front face direction @fixme
// glFrontFace(state->frontFace);
// Apply line width
glLineWidth(state->lineWidth);
// apply smooth lines
if (state->smoothLineEnabled) {
glEnable(GL_LINE_SMOOTH);
} else {
glDisable(GL_LINE_SMOOTH);
}
// Apply point size
if (state->pointSizeEnabled) {
glEnable(GL_PROGRAM_POINT_SIZE);
glPointSize(state->pointSize);
} else {
glDisable(GL_PROGRAM_POINT_SIZE);
}
// Apply polygon mode
glPolygonMode(state->polygonModeFace, state->polygonModeMode);
// Apply scissor test
if (state->scissorTestEnabled) {
glEnable(GL_SCISSOR_TEST);
glScissor(state->scissorBox[0], state->scissorBox[1], state->scissorBox[2], state->scissorBox[3]);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
}
// ----------------------------------------------------------------------------
// shaders
@ -524,7 +672,7 @@ typedef map(unsigned,int) uniform_binding;
static __thread unsigned last_shader = -1;
static __thread quarks_db uniform_names;
static __thread map(handle, uniform_binding) uniforms;
static
int shader_uniform(const char *name) {
do_once map_init(uniforms, less_int, hash_int);
if (!map_find(uniforms, last_shader)) {
@ -1854,17 +2002,21 @@ void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
API vec4 window_getcolor_(); // internal use, not public
static renderstate_t skybox_rs;
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
//glClear(GL_DEPTH_BUFFER_BIT);
//glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
do_once {
skybox_rs = renderstate();
}
// we have to reset clear color here, because of wrong alpha compositing issues on native transparent windows otherwise
vec4 bgcolor = window_getcolor_(); glClearColor(bgcolor.r, bgcolor.g, bgcolor.b, 1); // @transparent
vec4 bgcolor = window_getcolor_();
skybox_rs.clearColor[0] = bgcolor.r;
skybox_rs.clearColor[1] = bgcolor.g;
skybox_rs.clearColor[2] = bgcolor.b;
skybox_rs.clearColor[3] = 1; // @transparent
mat44 mvp; multiply44x2(mvp, proj, view);
@ -1874,6 +2026,8 @@ int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
if( sky->flags ) {
shader_cubemap("u_cubemap", sky->cubemap.id);
}
renderstate_apply(&skybox_rs);
return 0; // @fixme: return sortable hash here?
}
int skybox_pop_state() {
@ -1884,7 +2038,6 @@ int skybox_pop_state() {
}
int skybox_render(skybox_t *sky, mat44 proj, mat44 view) {
skybox_push_state(sky, proj, view);
glEnable(GL_DEPTH_TEST);
mesh_render(&sky->geometry);
skybox_pop_state();
return 0;
@ -3543,6 +3696,11 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model,
model_t model_from_mem(const void *mem, int len, int flags) {
model_t m = {0};
{
m.rs = renderstate();
m.rs.blendEnabled = 1;
}
m.stored_flags = flags;
m.shading = SHADING_PHONG;
@ -3826,6 +3984,8 @@ void model_draw_call(model_t m, int shader) {
handle old_shader = last_shader;
shader_bind(shader);
renderstate_apply(&m.rs);
glBindVertexArray( q->vao );
struct iqmtriangle *tris = NULL;

View File

@ -8,6 +8,65 @@
typedef unsigned handle; // GLuint
// -----------------------------------------------------------------------------
// renderstate
typedef struct renderstate_t {
// Viewport parameters
int viewportX;
int viewportY;
int viewportWidth;
int viewportHeight;
// Clear color
float clearColor[4];
// Clear depth
double clearDepth;
// Depth test
bool depthTestEnabled;
unsigned depthFunc;
// Blending
bool blendEnabled;
unsigned blendFunc;
unsigned blendSrc;
unsigned blendDst;
// Culling
bool cullFaceEnabled;
unsigned cullFaceMode;
// Stencil test
bool stencilTestEnabled;
unsigned stencilFunc;
int stencilRef;
unsigned stencilMask;
// Face culling direction
unsigned frontFace; // GL_CW or GL_CCW
// Line width
bool smoothLineEnabled;
float lineWidth;
// Point size
bool pointSizeEnabled;
float pointSize;
// Polygon mode
unsigned polygonModeFace;
unsigned polygonModeMode;
// Scissor test
bool scissorTestEnabled;
int scissorBox[4];
} renderstate_t;
API renderstate_t renderstate();
API bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB);
API void renderstate_apply(const renderstate_t *state);
// -----------------------------------------------------------------------------
// colors
@ -228,6 +287,7 @@ API void shadowmatrix_ortho(mat44 shm_proj, float left, float right, float botto
API unsigned shader(const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_bind(unsigned program);
API int shader_uniform(const char *name);
API void shader_bool(const char *uniform, bool i );
API void shader_int(const char *uniform, int i);
API void shader_uint(const char *uniform, unsigned i );
@ -577,6 +637,7 @@ typedef struct model_t {
unsigned num_instances;
int stored_flags;
renderstate_t rs;
} model_t;
enum BILLBOARD_MODE {

View File

@ -33,6 +33,7 @@ typedef struct text2d_cmd {
float sca;
} text2d_cmd;
static renderstate_t dd_rs;
static uint32_t dd_color = ~0u;
static GLuint dd_program = -1;
static int dd_u_color = -1;
@ -66,7 +67,9 @@ void ddraw_flush() {
}
void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnable(GL_DEPTH_TEST);
do_once dd_rs = renderstate();
dd_rs.depthTestEnabled = 1;
glActiveTexture(GL_TEXTURE0);
mat44 mvp;
@ -81,16 +84,16 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnableVertexAttribArray(0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_PROGRAM_POINT_SIZE); // for GL_POINTS
glEnable(GL_LINE_SMOOTH); // for GL_LINES (thin)
dd_rs.pointSizeEnabled = 1;
dd_rs.smoothLineEnabled = 1;
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -119,10 +122,11 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp);
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -141,9 +145,6 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
array_resize(dd_text2d, 0);
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(0);
ddraw_color(WHITE); // reset color for next drawcall

View File

@ -221,7 +221,20 @@ struct nk_glfw *window_handle_nkglfw() {
return g->nk_glfw;
}
static renderstate_t window_rs;
void glNewFrame() {
do_once {
window_rs = renderstate();
window_rs.blendEnabled = 1;
window_rs.depthTestEnabled = 1;
}
window_rs.clearColor[0] = winbgcolor.r;
window_rs.clearColor[1] = winbgcolor.g;
window_rs.clearColor[2] = winbgcolor.b;
window_rs.clearColor[3] = window_has_transparent() ? 0 : winbgcolor.a;
// @transparent debug
// if( input_down(KEY_F1) ) window_transparent(window_has_transparent()^1);
// if( input_down(KEY_F2) ) window_maximize(window_has_maximize()^1);
@ -242,30 +255,8 @@ void glNewFrame() {
g->width = w;
g->height = h;
// blending defaults
glEnable(GL_BLEND);
renderstate_apply(&window_rs);
// culling defaults
// glEnable(GL_CULL_FACE);
// glCullFace(GL_BACK);
// glFrontFace(GL_CCW);
// depth-testing defaults
glEnable(GL_DEPTH_TEST);
// glDepthFunc(GL_LESS);
// depth-writing defaults
// glDepthMask(GL_TRUE);
// seamless cubemaps
// glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glViewport(0, 0, window_width(), window_height());
// GLfloat bgColor[4]; glGetFloatv(GL_COLOR_CLEAR_VALUE, bgColor);
glClearColor(winbgcolor.r, winbgcolor.g, winbgcolor.b, window_has_transparent() ? 0 : winbgcolor.a); // @transparent
//glClearColor(0.15,0.15,0.15,1);
//glClearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
}

View File

@ -10256,6 +10256,9 @@ typedef struct font_t {
// vbos
GLuint vbo_quad; // vec2: simply just a regular [0,1]x[0,1] quad
GLuint vbo_instances; // vec4: (char_pos_x, char_pos_y, char_index, color_index)
// render state
renderstate_t rs;
} font_t;
enum { FONTS_MAX = 10 };
@ -10594,6 +10597,16 @@ void font_face_from_mem(const char *tag, const void *ttf_data, unsigned ttf_len,
glUniform2f(glGetUniformLocation(f->program, "res_meta"), f->num_glyphs, 2);
glUniform1f(glGetUniformLocation(f->program, "num_colors"), FONT_MAX_COLORS);
(void)flags;
// set up pipeline
f->rs = renderstate();
f->rs.blendEnabled = 1;
f->rs.blendFunc = GL_FUNC_ADD;
f->rs.blendSrc = GL_SRC_ALPHA;
f->rs.blendDst = GL_ONE_MINUS_SRC_ALPHA;
f->rs.scissorTestEnabled = 1;
f->rs.depthTestEnabled = 0;
f->rs.cullFaceEnabled = 0;
}
void font_face(const char *tag, const char *filename_ttf, float font_size, unsigned flags) {
@ -10624,25 +10637,10 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glGetIntegerv(GL_TEXTURE_BINDING_1D, &last_texture2);
glGetIntegerv(GL_BLEND_SRC, &last_blend_src);
glGetIntegerv(GL_BLEND_DST, &last_blend_dst);
glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// @fixme: store existing scissor test setup
glEnable(GL_SCISSOR_TEST);
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
glDisable(GL_DEPTH_TEST);
f->rs.scissorBox[0] = rect.x;
f->rs.scissorBox[1] = window_height() - (rect.y+rect.w);
f->rs.scissorBox[2] = rect.z;
f->rs.scissorBox[3] = rect.w;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, f->texture_fontdata);
@ -10668,6 +10666,9 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glBindBuffer(GL_ARRAY_BUFFER, f->vbo_instances);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4*4*glyph_idx, glyph_data);
// setup pipeline
renderstate_apply(&f->rs);
// actual drawing
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, glyph_idx);
@ -10681,13 +10682,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_1D, last_texture2);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBindVertexArray(last_vertex_array);
glBlendFunc(last_blend_src, last_blend_dst);
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
}
// 1. call font_face() if it's the first time it's called.
@ -17222,6 +17217,154 @@ void glCopyBackbufferToTexture( texture_t *tex ) { // unused
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 0, 0, window_width(), window_height(), 0 );
}
// ----------------------------------------------------------------------------
// renderstate
renderstate_t renderstate() {
renderstate_t state = {0};
// Set default viewport parameters
state.viewportX = 0;
state.viewportY = 0;
state.viewportWidth = window_width();
state.viewportHeight = window_height();
// Set default clear color to black
state.clearColor[0] = 0.0f; // Red
state.clearColor[1] = 0.0f; // Green
state.clearColor[2] = 0.0f; // Blue
state.clearColor[3] = 1.0f; // Alpha
// Set default clear depth to maximum distance
state.clearDepth = 1.0;
// Enable depth test by default with less or equal function
state.depthTestEnabled = GL_TRUE;
state.depthFunc = GL_LEQUAL;
// Disable blending by default
state.blendEnabled = GL_FALSE;
state.blendFunc = GL_FUNC_ADD;
state.blendSrc = GL_ONE;
state.blendDst = GL_ZERO;
// Enable culling by default and cull back faces
state.cullFaceEnabled = GL_TRUE;
state.cullFaceMode = GL_BACK;
// Disable stencil test by default
state.stencilTestEnabled = GL_FALSE;
state.stencilFunc = GL_ALWAYS;
state.stencilRef = 0;
state.stencilMask = 0xFFFFFFFF;
// Set default front face to counter-clockwise
state.frontFace = GL_CCW;
// Set default line width
state.smoothLineEnabled = GL_FALSE;
state.lineWidth = 1.0f;
// Set default point size
state.pointSizeEnabled = GL_FALSE;
state.pointSize = 1.0f;
// Set default polygon mode to fill
state.polygonModeFace = GL_FRONT_AND_BACK;
state.polygonModeMode = GL_FILL;
// Disable scissor test by default
state.scissorTestEnabled = GL_FALSE;
state.scissorBox[0] = 0;
state.scissorBox[1] = 0;
state.scissorBox[2] = window_width();
state.scissorBox[3] = window_height();
return state;
}
bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB) {
return memcmp(stateA, stateB, sizeof(renderstate_t)) == 0;
}
void renderstate_apply(const renderstate_t *state) {
if (state != NULL) {
// Apply viewport parameters
glViewport(state->viewportX, state->viewportY, state->viewportWidth, state->viewportHeight);
// Apply clear color
glClearColor(state->clearColor[0], state->clearColor[1], state->clearColor[2], state->clearColor[3]);
// Apply clear depth
glClearDepth(state->clearDepth);
// Apply depth test
if (state->depthTestEnabled) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(state->depthFunc);
} else {
glDisable(GL_DEPTH_TEST);
}
// Apply blending
if (state->blendEnabled) {
glEnable(GL_BLEND);
glBlendEquation(state->blendFunc);
glBlendFunc(state->blendSrc, state->blendDst);
} else {
glDisable(GL_BLEND);
}
// Apply culling @fixme
// if (state->cullFaceEnabled) {
// glEnable(GL_CULL_FACE);
// glCullFace(state->cullFaceMode);
// } else {
// glDisable(GL_CULL_FACE);
// }
// Apply stencil test
if (state->stencilTestEnabled) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(state->stencilFunc, state->stencilRef, state->stencilMask);
} else {
glDisable(GL_STENCIL_TEST);
}
// Apply front face direction @fixme
// glFrontFace(state->frontFace);
// Apply line width
glLineWidth(state->lineWidth);
// apply smooth lines
if (state->smoothLineEnabled) {
glEnable(GL_LINE_SMOOTH);
} else {
glDisable(GL_LINE_SMOOTH);
}
// Apply point size
if (state->pointSizeEnabled) {
glEnable(GL_PROGRAM_POINT_SIZE);
glPointSize(state->pointSize);
} else {
glDisable(GL_PROGRAM_POINT_SIZE);
}
// Apply polygon mode
glPolygonMode(state->polygonModeFace, state->polygonModeMode);
// Apply scissor test
if (state->scissorTestEnabled) {
glEnable(GL_SCISSOR_TEST);
glScissor(state->scissorBox[0], state->scissorBox[1], state->scissorBox[2], state->scissorBox[3]);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
}
// ----------------------------------------------------------------------------
// shaders
@ -17696,7 +17839,7 @@ typedef map(unsigned,int) uniform_binding;
static __thread unsigned last_shader = -1;
static __thread quarks_db uniform_names;
static __thread map(handle, uniform_binding) uniforms;
static
int shader_uniform(const char *name) {
do_once map_init(uniforms, less_int, hash_int);
if (!map_find(uniforms, last_shader)) {
@ -19026,17 +19169,21 @@ void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) {
API vec4 window_getcolor_(); // internal use, not public
static renderstate_t skybox_rs;
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
//glClear(GL_DEPTH_BUFFER_BIT);
//glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
do_once {
skybox_rs = renderstate();
}
// we have to reset clear color here, because of wrong alpha compositing issues on native transparent windows otherwise
vec4 bgcolor = window_getcolor_(); glClearColor(bgcolor.r, bgcolor.g, bgcolor.b, 1); // @transparent
vec4 bgcolor = window_getcolor_();
skybox_rs.clearColor[0] = bgcolor.r;
skybox_rs.clearColor[1] = bgcolor.g;
skybox_rs.clearColor[2] = bgcolor.b;
skybox_rs.clearColor[3] = 1; // @transparent
mat44 mvp; multiply44x2(mvp, proj, view);
@ -19046,6 +19193,8 @@ int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
if( sky->flags ) {
shader_cubemap("u_cubemap", sky->cubemap.id);
}
renderstate_apply(&skybox_rs);
return 0; // @fixme: return sortable hash here?
}
int skybox_pop_state() {
@ -19056,7 +19205,6 @@ int skybox_pop_state() {
}
int skybox_render(skybox_t *sky, mat44 proj, mat44 view) {
skybox_push_state(sky, proj, view);
glEnable(GL_DEPTH_TEST);
mesh_render(&sky->geometry);
skybox_pop_state();
return 0;
@ -20715,6 +20863,11 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model,
model_t model_from_mem(const void *mem, int len, int flags) {
model_t m = {0};
{
m.rs = renderstate();
m.rs.blendEnabled = 1;
}
m.stored_flags = flags;
m.shading = SHADING_PHONG;
@ -20998,6 +21151,8 @@ void model_draw_call(model_t m, int shader) {
handle old_shader = last_shader;
shader_bind(shader);
renderstate_apply(&m.rs);
glBindVertexArray( q->vao );
struct iqmtriangle *tris = NULL;
@ -21296,6 +21451,7 @@ typedef struct text2d_cmd {
float sca;
} text2d_cmd;
static renderstate_t dd_rs;
static uint32_t dd_color = ~0u;
static GLuint dd_program = -1;
static int dd_u_color = -1;
@ -21329,7 +21485,9 @@ void ddraw_flush() {
}
void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnable(GL_DEPTH_TEST);
do_once dd_rs = renderstate();
dd_rs.depthTestEnabled = 1;
glActiveTexture(GL_TEXTURE0);
mat44 mvp;
@ -21344,16 +21502,16 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glEnableVertexAttribArray(0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_PROGRAM_POINT_SIZE); // for GL_POINTS
glEnable(GL_LINE_SMOOTH); // for GL_LINES (thin)
dd_rs.pointSizeEnabled = 1;
dd_rs.smoothLineEnabled = 1;
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -21382,10 +21540,11 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp);
for( int i = 0; i < 3; ++i ) { // [0] thin, [1] thick, [2] points
GLenum mode = i < 2 ? GL_LINES : GL_POINTS;
glLineWidth(i == 1 ? 1 : 0.3); // 0.625);
dd_rs.lineWidth = (i == 1 ? 1 : 0.3); // 0.625);
for each_map(dd_lists[dd_ontop][i], unsigned, rgb, array(vec3), list) {
int count = array_count(list);
if(!count) continue;
renderstate_apply(&dd_rs);
// color
vec3 rgbf = {((rgb>>0)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>16)&255)/255.f};
glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x);
@ -21404,9 +21563,6 @@ void ddraw_flush_projview(mat44 proj, mat44 view) {
array_resize(dd_text2d, 0);
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(0);
ddraw_color(WHITE); // reset color for next drawcall
@ -26682,7 +26838,20 @@ struct nk_glfw *window_handle_nkglfw() {
return g->nk_glfw;
}
static renderstate_t window_rs;
void glNewFrame() {
do_once {
window_rs = renderstate();
window_rs.blendEnabled = 1;
window_rs.depthTestEnabled = 1;
}
window_rs.clearColor[0] = winbgcolor.r;
window_rs.clearColor[1] = winbgcolor.g;
window_rs.clearColor[2] = winbgcolor.b;
window_rs.clearColor[3] = window_has_transparent() ? 0 : winbgcolor.a;
// @transparent debug
// if( input_down(KEY_F1) ) window_transparent(window_has_transparent()^1);
// if( input_down(KEY_F2) ) window_maximize(window_has_maximize()^1);
@ -26703,30 +26872,8 @@ void glNewFrame() {
g->width = w;
g->height = h;
// blending defaults
glEnable(GL_BLEND);
renderstate_apply(&window_rs);
// culling defaults
// glEnable(GL_CULL_FACE);
// glCullFace(GL_BACK);
// glFrontFace(GL_CCW);
// depth-testing defaults
glEnable(GL_DEPTH_TEST);
// glDepthFunc(GL_LESS);
// depth-writing defaults
// glDepthMask(GL_TRUE);
// seamless cubemaps
// glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glViewport(0, 0, window_width(), window_height());
// GLfloat bgColor[4]; glGetFloatv(GL_COLOR_CLEAR_VALUE, bgColor);
glClearColor(winbgcolor.r, winbgcolor.g, winbgcolor.b, window_has_transparent() ? 0 : winbgcolor.a); // @transparent
//glClearColor(0.15,0.15,0.15,1);
//glClearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
}

View File

@ -3097,6 +3097,65 @@ API int ui_reflect(const char *mask); // *, model* or NULL
typedef unsigned handle; // GLuint
// -----------------------------------------------------------------------------
// renderstate
typedef struct renderstate_t {
// Viewport parameters
int viewportX;
int viewportY;
int viewportWidth;
int viewportHeight;
// Clear color
float clearColor[4];
// Clear depth
double clearDepth;
// Depth test
bool depthTestEnabled;
unsigned depthFunc;
// Blending
bool blendEnabled;
unsigned blendFunc;
unsigned blendSrc;
unsigned blendDst;
// Culling
bool cullFaceEnabled;
unsigned cullFaceMode;
// Stencil test
bool stencilTestEnabled;
unsigned stencilFunc;
int stencilRef;
unsigned stencilMask;
// Face culling direction
unsigned frontFace; // GL_CW or GL_CCW
// Line width
bool smoothLineEnabled;
float lineWidth;
// Point size
bool pointSizeEnabled;
float pointSize;
// Polygon mode
unsigned polygonModeFace;
unsigned polygonModeMode;
// Scissor test
bool scissorTestEnabled;
int scissorBox[4];
} renderstate_t;
API renderstate_t renderstate();
API bool renderstate_compare(const renderstate_t *stateA, const renderstate_t *stateB);
API void renderstate_apply(const renderstate_t *state);
// -----------------------------------------------------------------------------
// colors
@ -3317,6 +3376,7 @@ API void shadowmatrix_ortho(mat44 shm_proj, float left, float right, float botto
API unsigned shader(const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines);
API unsigned shader_bind(unsigned program);
API int shader_uniform(const char *name);
API void shader_bool(const char *uniform, bool i );
API void shader_int(const char *uniform, int i);
API void shader_uint(const char *uniform, unsigned i );
@ -3666,6 +3726,7 @@ typedef struct model_t {
unsigned num_instances;
int stored_flags;
renderstate_t rs;
} model_t;
enum BILLBOARD_MODE {