mirror of
https://github.com/quelsolaar/MergeSource
synced 2025-02-01 09:58:42 -05:00
1012 lines
33 KiB
C
1012 lines
33 KiB
C
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "forge.h"
|
|
#include "r_include.h"
|
|
|
|
|
|
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
|
|
|
uint r_sampler_names[] = {0x0DE0, /*GL_TEXTURE_1D*/
|
|
GL_TEXTURE_2D,
|
|
0x806F/*GL_TEXTURE_3D*/,
|
|
0x8513/*GL_TEXTURE_CUBE_MAP*/,
|
|
0x84F5 /*GL_TEXTURE_RECTANGLE*/,
|
|
-1/*GL_TEXTURE_1D_ARRAY*/,
|
|
-1/*GL_TEXTURE_2D_ARRAY*/,
|
|
0x9009 /*GL_TEXTURE_CUBE_MAP_ARRAY*/,
|
|
0x8C2A /*GL_TEXTURE_BUFFER*/,
|
|
0x9100 /*GL_TEXTURE_2D_MULTISAMPLE*/,
|
|
0x9102 /*GL_TEXTURE_2D_MULTISAMPLE_ARRAY*/};
|
|
|
|
GLhandleARB (APIENTRY *r_glCreateShaderObjectARB)(GLenum shaderType);
|
|
GLvoid (APIENTRY *r_glDeleteObjectARB)(GLhandleARB obj);
|
|
GLhandleARB (APIENTRY *r_glCreateProgramObjectARB)(GLvoid);
|
|
GLvoid (APIENTRY *r_glAttachObjectARB)(GLhandleARB containerObj, GLhandleARB obj);
|
|
GLvoid (APIENTRY *r_glShaderSourceARB)(GLhandleARB shaderObj, GLsizei count, const char **string, const GLint *length);
|
|
GLvoid (APIENTRY *r_glCompileShaderARB)(GLhandleARB shaderObj);
|
|
GLvoid (APIENTRY *r_glLinkProgramARB)(GLhandleARB programObj);
|
|
GLvoid (APIENTRY *r_glUseProgramObjectARB)(GLhandleARB programObj);
|
|
GLint (APIENTRY *r_glGetUniformLocationARB)(GLhandleARB programObj, const char *name);
|
|
GLvoid (APIENTRY *r_glUniform4fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
|
GLvoid (APIENTRY *r_glUniform3fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
|
GLvoid (APIENTRY *r_glUniform2fARB)(GLint location, GLfloat v0, GLfloat v1);
|
|
GLvoid (APIENTRY *r_glUniform1fARB)(GLint location, GLfloat v0);
|
|
GLvoid (APIENTRY *r_glUniform1iARB)(GLint location, GLint i);
|
|
GLvoid (APIENTRY *r_glUniform2iARB)(GLint location, GLint i0, GLint i1);
|
|
GLvoid (APIENTRY *r_glUniform3iARB)(GLint location, GLint i0, GLint i1, GLint i2);
|
|
GLvoid (APIENTRY *r_glUniform4iARB)(GLint location, GLint i0, GLint i1, GLint i2, GLint i3);
|
|
GLvoid (APIENTRY *r_glUniformMatrix4fvARB)(GLint location, GLsizei count, GLboolean transpose, GLfloat *value);
|
|
GLvoid (APIENTRY *r_glUniformMatrix3fvARB)(GLint location, GLsizei count, GLboolean transpose, GLfloat *value);
|
|
GLvoid (APIENTRY *r_glUniformMatrix2fvARB)(GLint location, GLsizei count, GLboolean transpose, GLfloat *value);
|
|
GLvoid (APIENTRY *r_glGetShaderivARB)(GLuint shader, GLenum pname, GLint *params);
|
|
GLvoid (APIENTRY *r_glGetProgramivARB)(GLuint shader, GLenum pname, GLint *params);
|
|
GLint (APIENTRY *r_glGetProgramiARB)(GLuint shader, GLenum pname);
|
|
|
|
GLint (APIENTRY *r_glGetAttribLocationARB)(GLhandleARB programObj, const char *name);
|
|
GLvoid (APIENTRY *r_glVertexAttrib4fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
|
GLvoid (APIENTRY *r_glActiveTextureARB)(GLenum texture);
|
|
|
|
GLvoid (APIENTRY *r_glBindAttribLocationARB)(GLhandleARB programObj, GLuint index, const char *name);
|
|
|
|
GLvoid (APIENTRY *r_glGetShaderInfoLog)(GLhandleARB object, GLsizei maxLenght, GLsizei *length, char *infoLog);
|
|
GLvoid (APIENTRY *r_glGetProgramInfoLog)(GLhandleARB object, GLsizei maxLenght, GLsizei *length, char *infoLog);
|
|
|
|
GLvoid (APIENTRY *r_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask);
|
|
GLvoid (APIENTRY *r_glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
|
|
|
/* From buffer */
|
|
|
|
extern GLvoid (APIENTRY *r_glGenBuffersARB)(uint n, uint *buffers);
|
|
extern GLvoid (APIENTRY *r_glBindBufferARB)(uint target, uint buffer);
|
|
extern GLvoid (APIENTRY *r_glBufferDataARB)(uint target, uint size, const void *data, uint usage);
|
|
|
|
GLvoid (APIENTRY *r_glBindTextures)(GLuint first, GLsizei count, const GLuint *textures);
|
|
|
|
GLvoid (APIENTRY *r_glTransformFeedbackVaryings)(GLuint program, GLsizei count, const char **varyings, GLenum bufferMode);
|
|
#define GL_INTERLEAVED_ATTRIBS 0x8C8C
|
|
|
|
|
|
/* From experimental */
|
|
|
|
GLuint (APIENTRY *r_glGetUniformBlockIndex)(GLuint program, const char *uniformBlockName);
|
|
extern void (APIENTRY *r_glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
|
|
void (APIENTRY *r_glBindBufferBase)(GLenum target, GLuint index, GLuint buffer);
|
|
extern void (APIENTRY *r_glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
|
|
GLuint (APIENTRY *r_glGetUniformIndices)(GLuint program, GLsizei uniformCount, const char **uniformNames, GLuint *uniformIndices);
|
|
void (APIENTRY *r_glGetActiveUniformsiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
|
|
void (APIENTRY *r_glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
|
|
void (APIENTRY *r_gluniform3fvARB)(GLint location, uint count, GLfloat *v);
|
|
|
|
GLuint (APIENTRY *r_glGetProgramResourceIndex)(GLuint program,GLenum programInterface, const char * name);
|
|
void (APIENTRY *r_glShaderStorageBlockBinding)(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
|
|
|
|
|
|
RShader *r_current_shader = NULL;
|
|
uint p_current_textures[64] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
|
|
|
|
|
RState r_current_state;
|
|
uint r_shader_glsl_version;
|
|
|
|
uint r_shader_experimental_program_get(RShader *shader)
|
|
{
|
|
return shader->program;
|
|
}
|
|
|
|
void r_shader_state_set_default(RState *state)
|
|
{
|
|
uint i;
|
|
state->depth_test = GL_LEQUAL;
|
|
// state->depth_test = GL_GEQUAL;
|
|
state->cull_face = 0;
|
|
state->blend_dest = GL_ONE_MINUS_SRC_ALPHA;
|
|
state->blend_source = GL_SRC_ALPHA;
|
|
state->offset_factor = 0;
|
|
state->offset_units = 0;
|
|
state->alpha_to_coverage = FALSE;
|
|
state->depth_mask = TRUE;
|
|
state->color_mask[0] = TRUE;
|
|
state->color_mask[1] = TRUE;
|
|
state->color_mask[2] = TRUE;
|
|
state->color_mask[3] = TRUE;
|
|
for(i = 0; i < 2; i++)
|
|
{
|
|
state->steincil[i].function = GL_ALWAYS;
|
|
state->steincil[i].reference = 0;
|
|
state->steincil[i].mask = 0;
|
|
state->steincil[i].stencil_fail_op = GL_KEEP;
|
|
state->steincil[i].depth_fail_op = GL_KEEP;
|
|
state->steincil[i].sucsess_op = GL_KEEP;
|
|
}
|
|
}
|
|
|
|
void r_shader_state_set(RState *state)
|
|
{
|
|
|
|
// if(r_current_state.depth_test != state->depth_test)
|
|
{
|
|
/* if(state->depth_test == 0)
|
|
glDisable(GL_DEPTH_TEST);
|
|
else
|
|
{
|
|
// if(r_current_state.depth_test == 0)*/
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthFunc(state->depth_test);
|
|
// }
|
|
}
|
|
// if(r_current_state.cull_face != state->cull_face)
|
|
{
|
|
if(state->cull_face == 0)
|
|
glDisable(GL_CULL_FACE);
|
|
else
|
|
{
|
|
if(r_current_state.cull_face == 0)
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(state->cull_face);
|
|
}
|
|
}
|
|
|
|
// if(r_current_state.blend_dest != state->blend_dest ||
|
|
// r_current_state.blend_source != state->blend_source)
|
|
|
|
glEnable(GL_BLEND);
|
|
{
|
|
glBlendFunc(state->blend_source, state->blend_dest);
|
|
|
|
}
|
|
// glBlendFunc(1, 1);
|
|
|
|
// if(r_current_state.offset_factor != state->offset_factor ||
|
|
// r_current_state.offset_units != state->offset_units)
|
|
// glPolygonOffset(state->offset_units, state->offset_units);
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
glPolygonOffset(state->offset_units, state->offset_units);
|
|
|
|
// if(r_current_state.alpha_to_coverage != state->alpha_to_coverage)
|
|
{
|
|
if(state->alpha_to_coverage)
|
|
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
|
else
|
|
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
|
}
|
|
|
|
// if(r_current_state.depth_mask != state->depth_mask)
|
|
glDepthMask(state->depth_mask);
|
|
// glDepthMask(FALSE);
|
|
|
|
// if(r_current_state.color_mask[0] != state->color_mask[0] ||
|
|
// r_current_state.color_mask[1] != state->color_mask[1] ||
|
|
// r_current_state.color_mask[2] != state->color_mask[2] ||
|
|
// r_current_state.color_mask[3] != state->color_mask[3])
|
|
glColorMask(state->color_mask[0], state->color_mask[1], state->color_mask[2], state->color_mask[3]);
|
|
|
|
if(r_glStencilFuncSeparate != NULL)
|
|
{
|
|
r_glStencilFuncSeparate(GL_FRONT, state->steincil[0].function, state->steincil[0].reference, state->steincil[0].mask);
|
|
r_glStencilFuncSeparate(GL_BACK, state->steincil[1].function, state->steincil[1].reference, state->steincil[1].mask);
|
|
}else
|
|
glStencilFunc(state->steincil[0].function, state->steincil[0].reference, state->steincil[0].mask);
|
|
if(r_glStencilOpSeparate != NULL)
|
|
{
|
|
r_glStencilOpSeparate(GL_FRONT, state->steincil[0].stencil_fail_op, state->steincil[0].depth_fail_op, state->steincil[0].sucsess_op);
|
|
r_glStencilOpSeparate(GL_BACK, state->steincil[1].stencil_fail_op, state->steincil[1].depth_fail_op, state->steincil[1].sucsess_op);
|
|
}else
|
|
glStencilOp(state->steincil[0].stencil_fail_op, state->steincil[0].depth_fail_op, state->steincil[0].sucsess_op);
|
|
|
|
r_current_state = *state;
|
|
}
|
|
|
|
|
|
void r_shader_state_set_depth_test(RShader *shader, uint depth_test)
|
|
{
|
|
uint i;
|
|
if(r_shader_presets_get(P_SP_COLOR_UNIFORM) == shader)
|
|
i = 0;
|
|
|
|
if(r_current_shader == shader)
|
|
{
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthFunc(depth_test);
|
|
}
|
|
shader->state.depth_test = depth_test;
|
|
}
|
|
|
|
void r_shader_state_set_cull_face(RShader *shader, uint cull_face)
|
|
{
|
|
|
|
if(r_current_shader == shader)
|
|
{
|
|
if(cull_face == 0)
|
|
glDisable(GL_CULL_FACE);
|
|
else
|
|
{
|
|
if(r_current_state.cull_face == 0)
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(cull_face);
|
|
}
|
|
}
|
|
shader->state.cull_face = cull_face;
|
|
}
|
|
|
|
void r_shader_state_set_blend_mode(RShader *shader, uint blend_source, uint blend_destination)
|
|
{
|
|
if(r_current_shader == shader)
|
|
glBlendFunc(blend_source, blend_destination);
|
|
shader->state.blend_dest = blend_destination;
|
|
shader->state.blend_source = blend_source;
|
|
}
|
|
|
|
void r_shader_state_set_offset(RShader *shader, float offset_factor, float offset_units)
|
|
{
|
|
if(r_current_shader == shader)
|
|
glPolygonOffset(offset_units, offset_units);
|
|
shader->state.offset_factor = offset_factor;
|
|
shader->state.offset_units = offset_units;
|
|
}
|
|
|
|
void r_shader_state_set_alpha_to_coverage(RShader *shader, boolean alpha_to_coverage)
|
|
{
|
|
if(r_current_shader == shader)
|
|
{
|
|
if(alpha_to_coverage)
|
|
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
|
else
|
|
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
|
}
|
|
shader->state.alpha_to_coverage = alpha_to_coverage;
|
|
}
|
|
|
|
void r_shader_state_set_mask(RShader *shader, boolean red, boolean green, boolean blue, boolean alpha, boolean depth)
|
|
{
|
|
uint i;
|
|
if(r_shader_presets_get(P_SP_COLOR_UNIFORM) == shader)
|
|
i = 0;
|
|
if(r_current_shader == shader)
|
|
{
|
|
glDepthMask(depth);
|
|
glColorMask(red, green, blue, alpha);
|
|
}
|
|
|
|
shader->state.depth_mask = depth;
|
|
shader->state.color_mask[0] = red;
|
|
shader->state.color_mask[1] = green;
|
|
shader->state.color_mask[2] = blue;
|
|
shader->state.color_mask[3] = alpha;
|
|
}
|
|
|
|
typedef enum{
|
|
R_SF_NEVER,
|
|
R_SF_ALWAYS,
|
|
R_SF_LESS,
|
|
R_SF_LESS_OR_EQUAL,
|
|
R_SF_GREATER,
|
|
R_SF_GREATER_OR_EQUAL,
|
|
R_SF_EQUAL,
|
|
R_SF_NOT_EQUAL,
|
|
R_SF_COUNT
|
|
}RStencilFunc;
|
|
|
|
typedef enum{
|
|
R_SO_KEEP,
|
|
R_SO_INVERT,
|
|
R_SO_ZERO,
|
|
R_SO_REPLACE,
|
|
R_SO_INCR,
|
|
R_SO_INCR_WRAP,
|
|
R_SO_DECR,
|
|
R_SO_DECR_WRAP
|
|
}RStencilOp;
|
|
|
|
void r_shader_state_set_stencil(RShader *shader, boolean front, RStencilFunc function, uint32 reference, uint32 mask, RStencilOp stencil_fail_op, RStencilOp depth_fail_op, RStencilOp sucsess_op)
|
|
{
|
|
uint side = 0, gl_enum;
|
|
uint32 func_convert[] = {GL_NEVER,
|
|
GL_ALWAYS,
|
|
GL_LESS,
|
|
GL_LEQUAL,
|
|
GL_GREATER,
|
|
GL_GEQUAL,
|
|
GL_EQUAL,
|
|
GL_NOTEQUAL};
|
|
uint32 op_convert[] = {GL_KEEP,
|
|
GL_INVERT,
|
|
GL_ZERO,
|
|
GL_REPLACE,
|
|
GL_INCR,
|
|
0x8507,
|
|
GL_DECR,
|
|
0x8508};
|
|
if(!front)
|
|
side = 1;
|
|
shader->state.steincil[side].function = func_convert[function];
|
|
shader->state.steincil[side].reference = reference;
|
|
shader->state.steincil[side].mask = mask;
|
|
shader->state.steincil[side].stencil_fail_op = op_convert[stencil_fail_op];
|
|
shader->state.steincil[side].depth_fail_op = op_convert[depth_fail_op];
|
|
shader->state.steincil[side].sucsess_op = op_convert[sucsess_op];
|
|
if(r_current_shader == shader)
|
|
{
|
|
if(front)
|
|
gl_enum = GL_FRONT;
|
|
else
|
|
gl_enum = GL_BACK;
|
|
if(r_glStencilFuncSeparate == NULL)
|
|
r_glStencilFuncSeparate(gl_enum, shader->state.steincil[side].function, shader->state.steincil[side].reference, shader->state.steincil[side].mask);
|
|
else
|
|
glStencilFunc(shader->state.steincil[side].function, shader->state.steincil[side].reference, shader->state.steincil[side].mask);
|
|
if(r_glStencilOpSeparate)
|
|
r_glStencilOpSeparate(gl_enum, shader->state.steincil[side].stencil_fail_op, shader->state.steincil[side].depth_fail_op, shader->state.steincil[side].sucsess_op);
|
|
else
|
|
glStencilOp(shader->state.steincil[side].stencil_fail_op, shader->state.steincil[side].depth_fail_op, shader->state.steincil[side].sucsess_op);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boolean r_shader_init(void)
|
|
{
|
|
char *version;
|
|
RState state;
|
|
uint8 *data;
|
|
uint i, j, major = 0;
|
|
r_shader_glsl_version = 110;
|
|
version = glGetString(GL_SHADING_LANGUAGE_VERSION);
|
|
for(i = 0; version[i] != 0 && (version[i] < '0' || version[i] > '9'); i++);
|
|
j = i;
|
|
r_shader_glsl_version = 0;
|
|
for(; version[i] >= '0' && version[i] <= '9'; i++)
|
|
{
|
|
r_shader_glsl_version *= 10;
|
|
r_shader_glsl_version += version[i] - '0';
|
|
}
|
|
if(version[i] == '.')
|
|
{
|
|
i++;
|
|
for(j = 0; j < 2 && version[i] >= '0' && version[i] <= '9'; i++)
|
|
{
|
|
r_shader_glsl_version *= 10;
|
|
r_shader_glsl_version += version[i] - '0';
|
|
j++;
|
|
}
|
|
for(; j < 2; j++)
|
|
r_shader_glsl_version *= 10;
|
|
}
|
|
if(r_shader_glsl_version < 110)
|
|
{
|
|
printf("Relinquish Error: Failed to parse GLSL version string \"%s\". Revetring to GLSL version 110. ", version);
|
|
r_shader_glsl_version = 110;
|
|
}
|
|
#ifdef RELINQUISH_CONTEXT_OPENGLES
|
|
r_glCreateShaderObjectARB = glCreateShader;
|
|
r_glDeleteObjectARB = glDeleteShader;
|
|
r_glCreateProgramObjectARB = glCreateProgram;
|
|
r_glAttachObjectARB = glAttachShader;
|
|
r_glShaderSourceARB = glShaderSource;
|
|
r_glCompileShaderARB = glCompileShader;
|
|
r_glLinkProgramARB = glLinkProgram;
|
|
r_glUseProgramObjectARB = glUseProgram;
|
|
r_glGetUniformLocationARB = glGetUniformLocation;
|
|
r_glUniform4fARB = glUniform4f;
|
|
r_glUniform3fARB = glUniform3f;
|
|
r_glUniform2fARB = glUniform2f;
|
|
r_glUniform1fARB = glUniform1f;
|
|
r_glUniform1iARB = glUniform1i;
|
|
r_glUniform2iARB = glUniform2i;
|
|
r_glUniform3iARB = glUniform3i;
|
|
r_glUniform4iARB = glUniform4i;
|
|
r_glUniformMatrix4fvARB = glUniformMatrix4fv;
|
|
r_glUniformMatrix3fvARB = glUniformMatrix3fv;
|
|
r_glUniformMatrix2fvARB = glUniformMatrix2fv;
|
|
r_glGetShaderivARB = glGetShaderiv;
|
|
r_glGetProgramivARB = glGetProgramiv;
|
|
r_glBindAttribLocationARB = glBindAttribLocation;
|
|
r_glGetAttribLocationARB = glGetAttribLocation;
|
|
r_glVertexAttrib4fARB = glVertexAttrib4f;
|
|
r_glActiveTextureARB = glActiveTexture;
|
|
r_glGetShaderInfoLog = glGetShaderInfoLog;
|
|
r_glGetProgramInfoLog = glGetProgramInfoLog;
|
|
|
|
#endif
|
|
#ifdef RELINQUISH_CONTEXT_OPENGL
|
|
if(r_shader_glsl_version > 110 || r_extension_test("GL_ARB_shading_language_100"))
|
|
{
|
|
r_glCreateShaderObjectARB = r_extension_get_address("glCreateShaderObjectARB");
|
|
r_glDeleteObjectARB = r_extension_get_address("glDeleteObjectARB");
|
|
r_glCreateProgramObjectARB = r_extension_get_address("glCreateProgramObjectARB");
|
|
r_glAttachObjectARB = r_extension_get_address("glAttachObjectARB");
|
|
r_glShaderSourceARB = r_extension_get_address("glShaderSource");
|
|
r_glCompileShaderARB = r_extension_get_address("glCompileShaderARB");
|
|
r_glLinkProgramARB = r_extension_get_address("glLinkProgramARB");
|
|
r_glUseProgramObjectARB = r_extension_get_address("glUseProgramObjectARB");
|
|
r_glGetUniformLocationARB = r_extension_get_address("glGetUniformLocationARB");
|
|
r_glUniform4fARB = r_extension_get_address("glUniform4fARB");
|
|
r_glUniform3fARB = r_extension_get_address("glUniform3fARB");
|
|
r_glUniform2fARB = r_extension_get_address("glUniform2fARB");
|
|
r_glUniform1fARB = r_extension_get_address("glUniform1fARB");
|
|
r_glUniform1iARB = r_extension_get_address("glUniform1iARB");
|
|
r_glUniform2iARB = r_extension_get_address("glUniform2iARB");
|
|
r_glUniform3iARB = r_extension_get_address("glUniform3iARB");
|
|
r_glUniform4iARB = r_extension_get_address("glUniform4iARB");
|
|
r_glUniformMatrix4fvARB = r_extension_get_address("glUniformMatrix4fvARB");
|
|
r_glUniformMatrix3fvARB = r_extension_get_address("glUniformMatrix3fvARB");
|
|
r_glUniformMatrix2fvARB = r_extension_get_address("glUniformMatrix2fvARB");
|
|
r_glGetShaderivARB = r_extension_get_address("glGetShaderiv");
|
|
r_glGetProgramivARB = r_extension_get_address("glGetProgramivARB");
|
|
r_glBindAttribLocationARB = r_extension_get_address("glBindAttribLocationARB");
|
|
r_glGetAttribLocationARB = r_extension_get_address("glGetAttribLocationARB");
|
|
r_glVertexAttrib4fARB = r_extension_get_address("glVertexAttrib4fARB");
|
|
r_glActiveTextureARB = r_extension_get_address("glActiveTextureARB");
|
|
r_glGetShaderInfoLog = r_extension_get_address("glGetShaderInfoLog");
|
|
r_glGetProgramInfoLog = r_extension_get_address("glGetProgramInfoLog");
|
|
if(r_glGetShaderInfoLog == NULL)
|
|
r_glGetShaderInfoLog = r_extension_get_address("glGetInfoLogARB");
|
|
if(r_glGetProgramInfoLog == NULL)
|
|
r_glGetProgramInfoLog = r_extension_get_address("glGetInfoLogARB");
|
|
r_glTransformFeedbackVaryings = r_extension_get_address("glTransformFeedbackVaryings");
|
|
|
|
r_glStencilFuncSeparate = r_extension_get_address("glStencilFuncSeparate");
|
|
r_glStencilOpSeparate = r_extension_get_address("glStencilOpSeparate");
|
|
|
|
}else
|
|
return FALSE;
|
|
#endif
|
|
|
|
r_glBindTextures = r_extension_get_address("glBindTextures");
|
|
|
|
r_current_shader = NULL;
|
|
for(i = 0; i < 64; i++)
|
|
p_current_textures[i] = -1;
|
|
|
|
data = (uint8 *)&r_current_state;
|
|
for(i = 0; i < (sizeof r_current_state); i++)
|
|
data[i] = 255;
|
|
|
|
r_shader_state_set_default(&state);
|
|
r_shader_state_set(&state);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
#define GL_COMPILE_STATUS 0x8B81
|
|
#define GL_LINK_STATUS 0x8B82
|
|
|
|
extern void b_debug_message();
|
|
/*
|
|
GL_VERTEX_SHADER_ARB
|
|
GL_FRAGMENT_SHADER_ARB
|
|
*/
|
|
|
|
extern char *experimental_shader_vertex_test2;
|
|
extern char *experimental_shader_fragment_test2;
|
|
|
|
|
|
|
|
void r_shader_debug_print_uniform_buffer(RShader *shader, uint8 *uniform_buffer, char *text, uint buffer_id)
|
|
{
|
|
uint i, j, *ip, block_size = 0;
|
|
float *fp;
|
|
|
|
if(buffer_id == -1)
|
|
{
|
|
if(uniform_buffer == NULL)
|
|
uniform_buffer = shader->uniform_data;
|
|
buffer_id = 0;
|
|
for(i = 0; i < shader->uniform_data_size; i += 4)
|
|
{
|
|
if(i == block_size)
|
|
{
|
|
printf("Block %u : %s\n", buffer_id, shader->blocks[buffer_id].name);
|
|
block_size = shader->blocks[0].offset;
|
|
}
|
|
fp = (float *)&uniform_buffer[i];
|
|
ip = (uint *)&uniform_buffer[i];
|
|
printf("\tMem[%u] = u%u, f%f", i, ip[0], fp[0]);
|
|
for(j = 0; j < shader->uniform_count; j++)
|
|
{
|
|
if(shader->uniforms[j].offset + shader->blocks[shader->uniforms[j].block].offset == i)
|
|
{
|
|
printf(" %s %s", shader->uniforms[j].name, r_type_names[shader->uniforms[j].type]);
|
|
break;
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
}else
|
|
{
|
|
printf("Block %u : %s\n", buffer_id, shader->blocks[buffer_id].name);
|
|
block_size = shader->blocks[buffer_id].size;
|
|
if(uniform_buffer == NULL)
|
|
{
|
|
uniform_buffer = &shader->uniform_data[shader->blocks[buffer_id].offset];
|
|
if(buffer_id != shader->instance_block)
|
|
block_size *= shader->blocks[buffer_id].array_length;
|
|
}
|
|
for(i = 0; i < block_size; i += 4)
|
|
{
|
|
if(i % shader->blocks[buffer_id].size == 0 && i != 0)
|
|
printf("Array[%u]\n", i / shader->blocks[buffer_id].size);
|
|
|
|
fp = (float *)&uniform_buffer[i];
|
|
ip = (uint *)&uniform_buffer[i];
|
|
printf("\tMem[%u] = u%u, f%f", i, ip[0], fp[0]);
|
|
for(j = 0; j < shader->uniform_count; j++)
|
|
{
|
|
if(shader->uniforms[j].block == buffer_id &&
|
|
shader->uniforms[j].offset % shader->blocks[buffer_id].size == i)
|
|
{
|
|
printf(" %s", shader->uniforms[j].name);
|
|
break;
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void r_shader_debug_print_shader(RShader *shader)
|
|
{
|
|
printf("Reliquish Shader: %s:\n", shader->name);
|
|
switch(shader->mode)
|
|
{
|
|
case R_SIM_FLAT :
|
|
printf("Mode: R_SIM_FLAT - Uniforms are not merged in to blocks.\n");
|
|
break;
|
|
case R_SIM_UNIFORM_BLOCK :
|
|
printf("Mode: R_SIM_UNIFORM_BLOCK - Uniforms are merged in to blocks.\n");
|
|
break;
|
|
case R_SIM_BUFFER_OBJECT :
|
|
printf("Mode: R_SIM_BUFFER_OBJECT - Uniforms are merged in to blocks, and instance block is a Buffer object binding.\n");
|
|
break;
|
|
}
|
|
printf("Program ID: %u:\n", shader->program);
|
|
printf("Attributes: \n");
|
|
r_shader_parse_input_print(shader->attributes, shader->attribute_count);
|
|
printf("Uniforms: \n");
|
|
r_shader_parse_input_print(shader->uniforms, shader->uniform_count);
|
|
printf("Blocks: \n");
|
|
r_shader_parse_input_print(shader->blocks, shader->block_count);
|
|
printf("instance_block: %u - %s\n", shader->instance_block, shader->blocks[shader->instance_block].name);
|
|
|
|
|
|
if(shader->normal_matrix != -1 || shader->model_view_matrix != -1 || shader->projection_matrix != -1 || shader->model_view_projection_matrix != -1)
|
|
{
|
|
printf("Matrices: \n");
|
|
if(shader->normal_matrix != -1)
|
|
printf("\tnormal_matrix: %u\n", shader->normal_matrix);
|
|
if(shader->model_view_matrix != -1)
|
|
printf("\tmodel_view_matrix: %u\n", shader->model_view_matrix);
|
|
if(shader->projection_matrix != -1)
|
|
printf("\tprojection_matrix: %u\n", shader->projection_matrix);
|
|
if(shader->model_view_projection_matrix != -1)
|
|
printf("\tmodel_view_projection_matrix: %u\n", shader->model_view_projection_matrix);
|
|
}else
|
|
printf("No Built in Matrices\n");
|
|
printf("Uniform data size %u \n", shader->uniform_data_size);
|
|
r_shader_debug_print_uniform_buffer(shader, NULL, "Uniform buffer data", -1);
|
|
|
|
}
|
|
|
|
void r_test2()
|
|
{
|
|
if(r_glCreateShaderObjectARB == NULL)
|
|
exit(0);
|
|
}
|
|
|
|
|
|
|
|
char *r_shader_debug_override_shader = NULL;
|
|
uint r_shader_debug_override_stage = -1;
|
|
|
|
void r_shader_debug_override(char *shaders, uint stages)
|
|
{
|
|
r_shader_debug_override_shader = shaders;
|
|
r_shader_debug_override_stage = stages;
|
|
}
|
|
|
|
void *r_shader_create(char *debug_output, uint output_size, char **shaders, uint *stages, uint stage_count, char *name, char *instance_block)
|
|
{
|
|
static RShaderInput *input = NULL;
|
|
uint stage_obj[R_MAX_SHADER_STAGES], prog_obj, i, j, size = 0, add_size = 0, input_count, bind_point, texture_count;
|
|
int status;
|
|
RShader *shader;
|
|
char *text[2], *output[R_MAX_SHADER_STAGES];
|
|
if(input == NULL)
|
|
input = malloc((sizeof *input) * 256);
|
|
if(R_MAX_SHADER_STAGES < stage_count)
|
|
{
|
|
printf("Relinquish ERROR: Shader %s has too many stages (%u). the maximum number of stages is %u.\n", name, stage_count, R_MAX_SHADER_STAGES);
|
|
return NULL;
|
|
}
|
|
shader = malloc(sizeof *shader);
|
|
shader->uniforms = NULL;
|
|
shader->mode = R_SIM_UNIFORM_BLOCK;
|
|
if(r_glBindBufferBase != NULL) /* Test if uniffom bocks are available */
|
|
{
|
|
shader->mode = R_SIM_UNIFORM_BLOCK;
|
|
// shader->mode = R_SIM_BUFFER_OBJECT;
|
|
}else
|
|
shader->mode = R_SIM_FLAT;
|
|
shader->mode = R_SIM_FLAT;
|
|
// shader->mode = 0;
|
|
for(i = 0; i < 31 && name[i] != 0; i++)
|
|
shader->name[i] = name[i];
|
|
shader->name[i] = 0;
|
|
input_count = r_parse_shaders(output, shaders, stages, stage_count, input, shader->mode, r_shader_glsl_version, FALSE, instance_block, &shader->instance_block);
|
|
/* output[0] = experimental_shader_vertex_test2;
|
|
output[1] = experimental_shader_fragment_test2;*/
|
|
|
|
/* for(j = 0; j < stage_count; j++)
|
|
printf(shaders[j]);*/
|
|
if(r_shader_debug_override_stage < stage_count)
|
|
{
|
|
output[r_shader_debug_override_stage] = r_shader_debug_override_shader;
|
|
r_shader_debug_override_stage = -1;
|
|
}
|
|
|
|
for(i = 0; i < stage_count; i++)
|
|
{
|
|
char *read;
|
|
text[0] = output[i];
|
|
// text[0] = shaders[i];
|
|
read = output[i];
|
|
stage_obj[i] = r_glCreateShaderObjectARB(stages[i]);
|
|
r_glShaderSourceARB(stage_obj[i], 1, text/*(const char **)&vertex*/, NULL);
|
|
r_glCompileShaderARB(stage_obj[i]);
|
|
r_glGetShaderivARB(stage_obj[i], GL_COMPILE_STATUS, &status);
|
|
|
|
|
|
/* {
|
|
char log[2048];
|
|
uint size = 2048;
|
|
r_glGetShaderInfoLog(stage_obj[i], 2048, &size, log);
|
|
printf("LOG: %s\n", log);
|
|
}*/
|
|
|
|
if(!status)
|
|
{
|
|
if(debug_output == NULL)
|
|
{
|
|
output_size = 1024;
|
|
debug_output = malloc(output_size);
|
|
}
|
|
sprintf(debug_output, "RELINQUISH: Shader Debug: %s\n", name);
|
|
|
|
for(j = 0; j < stage_count; j++)
|
|
printf(output[j]);
|
|
// printf(shaders[j]);
|
|
|
|
for(add_size = 0; debug_output[add_size] != 0; add_size++);
|
|
output_size -= add_size;
|
|
r_glGetShaderInfoLog(stage_obj[i], output_size, &size, &debug_output[add_size]);
|
|
add_size += size;
|
|
output_size -= size;
|
|
for(j = 0; j < i + 1; j++)
|
|
r_glDeleteObjectARB(stage_obj[j]);
|
|
|
|
printf(debug_output);
|
|
exit(0);
|
|
// free(debug_output);
|
|
for(i = 0; i < stage_count; i++)
|
|
if(output[i] != r_shader_debug_override_shader)
|
|
free(output[i]);
|
|
return NULL;
|
|
}
|
|
}
|
|
shader->program = prog_obj = r_glCreateProgramObjectARB();
|
|
for(i = 0; i < stage_count; i++)
|
|
r_glAttachObjectARB(prog_obj, stage_obj[i]);
|
|
|
|
for(shader->attribute_count = i = 0; i < input_count; i++)
|
|
if(input[i].qualifyer == R_SIQ_ATTRIBUTE)
|
|
shader->attribute_count++;
|
|
shader->attributes = malloc((sizeof *shader->attributes) * shader->attribute_count);
|
|
if(shader->attribute_count == 0)
|
|
shader->attribute_count = 0;
|
|
shader->attribute_count = 0;
|
|
for(i = 0; i < input_count; i++)
|
|
{
|
|
if(input[i].qualifyer == R_SIQ_ATTRIBUTE)
|
|
{
|
|
shader->attributes[shader->attribute_count] = input[i];
|
|
shader->attributes[shader->attribute_count].id = shader->attribute_count;
|
|
r_glBindAttribLocationARB(prog_obj, shader->attribute_count, input[i].name);
|
|
shader->attribute_count++;
|
|
}
|
|
}
|
|
shader->buffer_output_component_count = 0;
|
|
if(r_glTransformFeedbackVaryings != NULL)
|
|
{
|
|
for(i = 1; i < stage_count && stages[i] != GL_FRAGMENT_SHADER_ARB; i++);
|
|
if(i < stage_count)
|
|
{
|
|
char *names[64];
|
|
uint output_count = 0;
|
|
for(j = 0; j < input_count; j++)
|
|
{
|
|
if(input[j].qualifyer == R_SIQ_INOUT && input[j].stages[i] && input[j].stages[i - 1])
|
|
{
|
|
names[output_count++] = input[j].name;
|
|
shader->buffer_input_component_types[shader->buffer_output_component_count++] = input[j].type;
|
|
}
|
|
}
|
|
r_glTransformFeedbackVaryings(prog_obj, output_count, names, GL_INTERLEAVED_ATTRIBS);
|
|
}
|
|
}
|
|
|
|
r_glLinkProgramARB(prog_obj);
|
|
r_glGetProgramivARB(prog_obj, GL_LINK_STATUS, &status);
|
|
if(!status)
|
|
{
|
|
if(debug_output == NULL)
|
|
{
|
|
output_size = 1024;
|
|
debug_output = malloc(output_size);
|
|
}
|
|
sprintf(debug_output, "RELINQUISH: Link Program Debug: %s\n", name);
|
|
for(add_size = 0; debug_output[add_size] != 0; add_size++);
|
|
output_size -= add_size;
|
|
r_glGetProgramInfoLog(prog_obj, output_size, &size, &debug_output[add_size]);
|
|
add_size += size;
|
|
output_size -= size;
|
|
printf(debug_output);
|
|
for(i = 0; i < stage_count; i++)
|
|
r_glDeleteObjectARB(stage_obj[i]);
|
|
printf(debug_output);
|
|
exit(0);
|
|
r_glDeleteObjectARB(prog_obj);
|
|
free(shader);
|
|
for(i = 0; i < stage_count; i++)
|
|
if(output[i] != r_shader_debug_override_shader)
|
|
free(output[i]);
|
|
return NULL;
|
|
}
|
|
r_glUseProgramObjectARB(prog_obj);
|
|
// r_experimental_print_uniforms(prog_obj);
|
|
|
|
for(i = 0; i < input_count; i++)
|
|
if(input[i].array_length == 0)
|
|
input[i].array_length = 1;
|
|
|
|
for(shader->uniform_count = i = 0; i < input_count; i++)
|
|
if(input[i].qualifyer == R_SIQ_UNIFORM)
|
|
shader->uniform_count++;
|
|
shader->uniforms = malloc((sizeof *shader->uniforms) * shader->uniform_count);
|
|
shader->uniform_count = 0;
|
|
texture_count = 0;
|
|
for(i = 0; i < input_count; i++)
|
|
{
|
|
if(input[i].qualifyer == R_SIQ_UNIFORM)
|
|
{
|
|
shader->uniforms[shader->uniform_count] = input[i];
|
|
shader->uniforms[shader->uniform_count].id = r_glGetUniformLocationARB(prog_obj, input[i].name);
|
|
if(shader->uniforms[shader->uniform_count].type >= R_TYPE_TEXTURE_START)
|
|
{
|
|
r_glUniform1iARB(shader->uniforms[shader->uniform_count].id, texture_count);
|
|
shader->uniforms[shader->uniform_count].id = texture_count++;
|
|
}
|
|
shader->uniform_count++;
|
|
}
|
|
}
|
|
|
|
for(shader->block_count = shader->uniform_data_size = i = 0; i < input_count; i++)
|
|
{
|
|
if(input[i].qualifyer == R_SIQ_BLOCK)
|
|
{
|
|
if(shader->instance_block == shader->block_count)
|
|
shader->uniform_data_size += input[i].size;
|
|
else
|
|
shader->uniform_data_size += input[i].size * input[i].array_length;
|
|
shader->block_count++;
|
|
}
|
|
}
|
|
shader->blocks = malloc((sizeof *shader->blocks) * shader->block_count);
|
|
shader->block_count = 0;
|
|
bind_point = 1;
|
|
for(i = 0; i < input_count; i++)
|
|
{
|
|
if(input[i].qualifyer == R_SIQ_BLOCK)
|
|
{
|
|
shader->blocks[shader->block_count] = input[i];
|
|
|
|
shader->blocks[shader->block_count].object = -1;
|
|
shader->blocks[shader->block_count].updated = FALSE;
|
|
for(j = 0; j < input_count && (input[j].block != shader->block_count || input[j].type < R_TYPE_TEXTURE_START); j++);
|
|
if(j < input_count)
|
|
shader->blocks[shader->block_count].qualifyer = R_SIQ_BLOCK_WITH_TEXTURE;
|
|
|
|
if(shader->mode != R_SIM_FLAT)
|
|
{
|
|
uint index;
|
|
if(shader->instance_block == shader->block_count)
|
|
j = 0;
|
|
else
|
|
j = bind_point++;
|
|
index = r_glGetUniformBlockIndex(shader->program, shader->blocks[shader->block_count].name);
|
|
if(index != -1)
|
|
r_glUniformBlockBinding(shader->program, index, j);
|
|
shader->blocks[shader->block_count].id = j;
|
|
if(shader->blocks[shader->block_count].qualifyer == R_SIQ_BLOCK || r_glGetTextureHandleARB != NULL)
|
|
{
|
|
r_glGenBuffersARB(1, &shader->blocks[shader->block_count].object);
|
|
r_glBindBufferARB(GL_UNIFORM_BUFFER, shader->blocks[shader->block_count].object);
|
|
r_glBufferDataARB(GL_UNIFORM_BUFFER, shader->blocks[shader->block_count].size * shader->blocks[shader->block_count].array_length, NULL, GL_DYNAMIC_DRAW_ARB);
|
|
}
|
|
}
|
|
shader->block_count++;
|
|
}
|
|
}
|
|
if(shader->mode != R_SIM_FLAT)
|
|
r_glBindBufferARB(GL_UNIFORM_BUFFER, 0);
|
|
if(shader->uniform_data_size != 0)
|
|
shader->uniform_data = malloc(shader->uniform_data_size);
|
|
else
|
|
shader->uniform_data = NULL;
|
|
|
|
if(debug_output != NULL)
|
|
{
|
|
r_glGetProgramInfoLog(prog_obj, output_size, &size, &debug_output[add_size]);
|
|
add_size += size;
|
|
output_size -= size;
|
|
}
|
|
r_shader_matrix_parse(shader);
|
|
r_shader_state_set_default(&shader->state);
|
|
for(i = 0; i < stage_count; i++)
|
|
if(output[i] != r_shader_debug_override_shader)
|
|
free(output[i]);
|
|
return shader;
|
|
}
|
|
|
|
void *r_shader_create_simple(char *debug_output, uint output_size, char *vertex, char *fragment, char *name)
|
|
{
|
|
char *shaders[2];
|
|
uint stages[2];
|
|
stages[0] = GL_VERTEX_SHADER_ARB;
|
|
stages[1] = GL_FRAGMENT_SHADER_ARB;
|
|
shaders[0] = vertex;
|
|
shaders[1] = fragment;
|
|
return r_shader_create(debug_output, output_size, shaders, stages, 2, name, NULL);
|
|
}
|
|
|
|
|
|
void *r_shader_create_from_file(char *debug_output, uint output_size, char *vertex_file, char *fragment_file, char *name)
|
|
{
|
|
RShader *shader;
|
|
uint size;
|
|
char *vertex, *fragment;
|
|
FILE *f;
|
|
f = fopen(vertex_file, "r");
|
|
if(f == NULL)
|
|
return 0;
|
|
fseek(f, 0, SEEK_END);
|
|
size = ftell(f);
|
|
rewind(f);
|
|
vertex = malloc(size + 1);
|
|
size = fread(vertex, 1, size, f);
|
|
fclose(f);
|
|
vertex[size] = 0;
|
|
f = fopen(fragment_file, "r");
|
|
if(f == NULL)
|
|
{
|
|
free(vertex);
|
|
return 0;
|
|
}
|
|
fseek(f, 0, SEEK_END);
|
|
size = ftell(f);
|
|
rewind(f);
|
|
fragment = malloc(size + 1);
|
|
size = fread(fragment, 1, size, f);
|
|
fclose(f);
|
|
fragment[size] = 0;
|
|
// printf(fragment);
|
|
// printf(vertex);
|
|
shader = r_shader_create_simple(debug_output, output_size, vertex, fragment, name);
|
|
free(fragment);
|
|
free(vertex);
|
|
return shader;
|
|
}
|
|
|
|
void r_shader_destroy(RShader *s)
|
|
{
|
|
if(s->attributes != NULL)
|
|
free(s->attributes);
|
|
if(s->uniforms != NULL)
|
|
free(s->uniforms);
|
|
if(s->blocks != NULL)
|
|
free(s->blocks);
|
|
r_glDeleteObjectARB(s->program);
|
|
free(s);
|
|
}
|
|
|
|
|
|
|
|
boolean r_shader_set(RShader *s)
|
|
{
|
|
if(s == NULL)
|
|
{
|
|
RState state;
|
|
r_glUseProgramObjectARB(0);
|
|
r_current_shader = NULL;
|
|
r_shader_state_set_default(&state);
|
|
r_shader_state_set(&state);
|
|
return TRUE;
|
|
}
|
|
if(r_current_shader != s)
|
|
{
|
|
r_shader_state_set(&s->state);
|
|
r_glUseProgramObjectARB(s->program);
|
|
r_current_shader = s;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void unbind_textures()
|
|
{
|
|
uint i;
|
|
for(i = 0; i < 64; i++)
|
|
{
|
|
r_glActiveTextureARB(GL_TEXTURE0_ARB + i);
|
|
glBindTexture(R_SIT_SAMPLER_2D, -1);
|
|
}
|
|
}
|
|
|
|
uint r_texture_gen(void *data, uint type, uint x_size, uint y_size, boolean alpha)
|
|
{
|
|
uint texture_id;
|
|
glGenTextures(1, &texture_id);
|
|
glBindTexture(GL_TEXTURE_2D, texture_id);
|
|
if(alpha)
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x_size, y_size, 0, GL_RGBA, type, data);
|
|
else
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, x_size, y_size, 0, GL_RGB, type, data);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
return texture_id;
|
|
}
|
|
|
|
void r_shader_texture_unit_set(RShader *s, char *name, uint id)
|
|
{
|
|
r_glUniform1iARB(r_glGetUniformLocationARB(s->program, name), id);
|
|
}
|
|
|
|
RFormats *r_shader_input_fomat_components_get(RShader *s)
|
|
{
|
|
return s->buffer_input_component_types;
|
|
}
|
|
|
|
uint r_shader_input_fomat_count_get(RShader *s)
|
|
{
|
|
return s->buffer_input_component_count;
|
|
}
|
|
|
|
RFormats *r_shader_output_fomat_components_get(RShader *s)
|
|
{
|
|
return s->buffer_output_component_types;
|
|
}
|
|
|
|
uint r_shader_output_fomat_count_get(RShader *s)
|
|
{
|
|
return s->buffer_output_component_count;
|
|
}
|
|
|
|
void *r_array_allocate(uint vertex_count, RFormats *vertex_format_types, uint *vertex_format_size, uint vertex_format_count, uint reference_count);
|
|
|
|
void *r_array_allocate_from_shader(RShader *s, uint vertex_count, uint reference_count, boolean in)
|
|
{
|
|
if(in)
|
|
return r_array_allocate(vertex_count, s->buffer_input_component_types, NULL, s->buffer_input_component_count, reference_count);
|
|
else
|
|
return r_array_allocate(vertex_count, s->buffer_output_component_types, NULL, s->buffer_output_component_count, reference_count);
|
|
}
|