mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-13 06:21:29 -10:00
This allows to use standard TrueType Fonts for text rendering in FSO. It uses the NanoVG library which provides the ability of drawing 2D shapes. This library is used for most 2D operations now and can also be used directly by using the PathRenderer class.
1746 lines
39 KiB
C++
1746 lines
39 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "graphics/gropengllight.h"
|
|
#include "graphics/gropenglshader.h"
|
|
#include "graphics/gropenglstate.h"
|
|
#include "math/vecmat.h"
|
|
|
|
extern GLfloat GL_max_anisotropy;
|
|
|
|
|
|
opengl_state GL_state;
|
|
|
|
|
|
opengl_texture_state::~opengl_texture_state()
|
|
{
|
|
if (units != NULL) {
|
|
vm_free(units);
|
|
}
|
|
}
|
|
|
|
void opengl_texture_state::init(GLuint n_units)
|
|
{
|
|
Assert( n_units > 0 );
|
|
units = (opengl_texture_unit*) vm_malloc(n_units * sizeof(opengl_texture_unit));
|
|
num_texture_units = n_units;
|
|
|
|
for (unsigned int unit = 0; unit < num_texture_units; unit++) {
|
|
units[unit].active = GL_FALSE;
|
|
units[unit].enabled = GL_FALSE;
|
|
units[unit].used = GL_FALSE;
|
|
|
|
default_values(unit);
|
|
|
|
glActiveTexture(GL_TEXTURE0 + unit);
|
|
if (unit < (GLuint)GL_supported_texture_units) {
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
glDisable(GL_TEXTURE_GEN_T);
|
|
glDisable(GL_TEXTURE_GEN_R);
|
|
glDisable(GL_TEXTURE_GEN_Q);
|
|
}
|
|
|
|
units[unit].texgen_S = GL_FALSE;
|
|
units[unit].texgen_T = GL_FALSE;
|
|
units[unit].texgen_R = GL_FALSE;
|
|
units[unit].texgen_Q = GL_FALSE;
|
|
|
|
if (unit < (GLuint)GL_supported_texture_units) {
|
|
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
}
|
|
|
|
units[unit].texgen_mode_S = GL_EYE_LINEAR;
|
|
units[unit].texgen_mode_T = GL_EYE_LINEAR;
|
|
units[unit].texgen_mode_R = GL_EYE_LINEAR;
|
|
units[unit].texgen_mode_Q = GL_EYE_LINEAR;
|
|
|
|
if (unit < (GLuint)GL_supported_texture_units) {
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
|
|
}
|
|
|
|
units[unit].env_mode = GL_MODULATE;
|
|
units[unit].env_combine_rgb = GL_MODULATE;
|
|
units[unit].env_combine_alpha = GL_MODULATE;
|
|
|
|
if (unit < (GLuint)GL_supported_texture_units) {
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0f);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
|
|
}
|
|
|
|
units[unit].rgb_scale = 1.0f;
|
|
units[unit].alpha_scale = 1.0f;
|
|
}
|
|
|
|
DisableAll();
|
|
}
|
|
|
|
void opengl_texture_state::default_values(GLint unit, GLenum target)
|
|
{
|
|
glActiveTexture(GL_TEXTURE0 + unit);
|
|
|
|
if (target == GL_INVALID_ENUM) {
|
|
if (unit < GL_supported_texture_units) {
|
|
glDisable(GL_TEXTURE_2D);
|
|
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
|
|
|
|
units[unit].texture_target = GL_TEXTURE_2D;
|
|
units[unit].texture_id = 0;
|
|
}
|
|
}
|
|
|
|
GLboolean opengl_texture_state::TexgenS(GLint state)
|
|
{
|
|
GLboolean save_state = units[active_texture_unit].texgen_S;
|
|
|
|
if ( !((state == -1) || (state == units[active_texture_unit].texgen_S)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_TEXTURE_GEN_S);
|
|
units[active_texture_unit].texgen_S = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
units[active_texture_unit].texgen_S = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_texture_state::TexgenT(GLint state)
|
|
{
|
|
GLboolean save_state = units[active_texture_unit].texgen_T;
|
|
|
|
if ( !((state == -1) || (state == units[active_texture_unit].texgen_T)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_TEXTURE_GEN_T);
|
|
units[active_texture_unit].texgen_T = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_TEXTURE_GEN_T);
|
|
units[active_texture_unit].texgen_T = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_texture_state::TexgenR(GLint state)
|
|
{
|
|
GLboolean save_state = units[active_texture_unit].texgen_R;
|
|
|
|
if ( !((state == -1) || (state == units[active_texture_unit].texgen_R)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_TEXTURE_GEN_R);
|
|
units[active_texture_unit].texgen_R = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_TEXTURE_GEN_R);
|
|
units[active_texture_unit].texgen_R = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_texture_state::TexgenQ(GLint state)
|
|
{
|
|
GLboolean save_state = units[active_texture_unit].texgen_Q;
|
|
|
|
if ( !((state == -1) || (state == units[active_texture_unit].texgen_Q)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_TEXTURE_GEN_Q);
|
|
units[active_texture_unit].texgen_Q = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_TEXTURE_GEN_Q);
|
|
units[active_texture_unit].texgen_Q = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
void opengl_texture_state::SetTarget(GLenum tex_target)
|
|
{
|
|
if (units[active_texture_unit].texture_target != tex_target) {
|
|
Disable();
|
|
|
|
if (units[active_texture_unit].texture_id) {
|
|
glBindTexture(units[active_texture_unit].texture_target, 0);
|
|
units[active_texture_unit].texture_id = 0;
|
|
}
|
|
|
|
// reset modes, since those were only valid for the previous texture target
|
|
default_values(active_texture_unit, tex_target);
|
|
units[active_texture_unit].texture_target = tex_target;
|
|
}
|
|
}
|
|
|
|
void opengl_texture_state::SetActiveUnit(GLuint id)
|
|
{
|
|
if (id >= num_texture_units) {
|
|
Int3();
|
|
id = 0;
|
|
}
|
|
|
|
glActiveTexture(GL_TEXTURE0 + id);
|
|
|
|
active_texture_unit = id;
|
|
}
|
|
|
|
void opengl_texture_state::Enable(GLuint tex_id)
|
|
{
|
|
units[active_texture_unit].used = GL_TRUE;
|
|
|
|
if ( units[active_texture_unit].active && (units[active_texture_unit].texture_id == tex_id) ) {
|
|
return;
|
|
}
|
|
|
|
if ( !shader_mode && (active_texture_unit < (uint)GL_supported_texture_units) ) {
|
|
if( units[active_texture_unit].texture_target != GL_TEXTURE_2D_ARRAY_EXT)
|
|
glEnable( units[active_texture_unit].texture_target );
|
|
units[active_texture_unit].enabled = GL_TRUE;
|
|
}
|
|
|
|
if (units[active_texture_unit].texture_id != tex_id) {
|
|
glBindTexture(units[active_texture_unit].texture_target, tex_id);
|
|
units[active_texture_unit].texture_id = tex_id;
|
|
}
|
|
|
|
units[active_texture_unit].active = GL_TRUE;
|
|
}
|
|
|
|
void opengl_texture_state::Disable()
|
|
{
|
|
if ( !units[active_texture_unit].active ) {
|
|
return;
|
|
}
|
|
|
|
if ( units[active_texture_unit].enabled ) {
|
|
if( units[active_texture_unit].texture_target != GL_TEXTURE_2D_ARRAY_EXT)
|
|
glDisable( units[active_texture_unit].texture_target );
|
|
units[active_texture_unit].enabled = GL_FALSE;
|
|
}
|
|
|
|
units[active_texture_unit].active = GL_FALSE;
|
|
units[active_texture_unit].used = GL_FALSE;
|
|
}
|
|
|
|
void opengl_texture_state::ResetUsed()
|
|
{
|
|
for (unsigned int i = 0; i < num_texture_units; i++) {
|
|
units[i].used = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
void opengl_texture_state::DisableUnused()
|
|
{
|
|
for (unsigned int i = 0; i < num_texture_units; i++) {
|
|
if (!units[i].used) {
|
|
SetActiveUnit(i);
|
|
Disable();
|
|
}
|
|
}
|
|
}
|
|
|
|
void opengl_texture_state::DisableAll()
|
|
{
|
|
for (unsigned int i = 0; i < num_texture_units; i++) {
|
|
if (units[i].active) {
|
|
SetActiveUnit(i);
|
|
Disable();
|
|
}
|
|
}
|
|
|
|
SetActiveUnit();
|
|
|
|
Current_texture_source = TEXTURE_SOURCE_NONE;
|
|
}
|
|
|
|
void opengl_texture_state::Delete(GLuint tex_id)
|
|
{
|
|
if (tex_id == 0) {
|
|
Int3();
|
|
return;
|
|
}
|
|
|
|
GLuint atu_save = active_texture_unit;
|
|
|
|
for (unsigned int i = 0; i < num_texture_units; i++) {
|
|
if (units[i].texture_id == tex_id) {
|
|
SetActiveUnit(i);
|
|
Disable();
|
|
|
|
glBindTexture(units[i].texture_target, 0);
|
|
units[i].texture_id = 0;
|
|
|
|
default_values(i, units[i].texture_target);
|
|
|
|
if (i == atu_save) {
|
|
atu_save = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetActiveUnit(atu_save);
|
|
}
|
|
|
|
GLfloat opengl_texture_state::AnisoFilter(GLfloat aniso)
|
|
{
|
|
#if 0
|
|
GLfloat rval = units[active_texture_unit].aniso_filter;
|
|
|
|
if ( (aniso > 0.0f) /*&& (aniso != rval)*/ ) {
|
|
if ( Is_Extension_Enabled(OGL_EXT_TEXTURE_FILTER_ANISOTROPIC) ) {
|
|
units[active_texture_unit].aniso_filter = aniso;
|
|
CLAMP(units[active_texture_unit].aniso_filter, 1.0f, GL_max_anisotropy);
|
|
|
|
glTexParameterf(units[active_texture_unit].texture_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, units[active_texture_unit].aniso_filter);
|
|
}
|
|
|
|
if ( Is_Extension_Enabled(OGL_EXT_TEXTURE_LOD_BIAS) ) {
|
|
if (units[active_texture_unit].aniso_filter > 1.0f) {
|
|
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
|
|
} else {
|
|
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.75f);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rval;
|
|
#endif
|
|
|
|
return GL_anisotropy;
|
|
}
|
|
|
|
opengl_state::~opengl_state()
|
|
{
|
|
if (light_Status != NULL) {
|
|
vm_free(light_Status);
|
|
}
|
|
}
|
|
|
|
void opengl_state::init()
|
|
{
|
|
int i;
|
|
|
|
glDisable(GL_FOG);
|
|
fog_Status = GL_FALSE;
|
|
|
|
glDisable(GL_BLEND);
|
|
blend_Status = GL_FALSE;
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
alphatest_Status = GL_FALSE;
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
depthtest_Status = GL_FALSE;
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
scissortest_Status = GL_FALSE;
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
cullface_Status = GL_FALSE;
|
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
polygonoffsetfill_Status = GL_FALSE;
|
|
|
|
polygon_offset_Factor = 0.0f;
|
|
polygon_offset_Unit = 0.0f;
|
|
|
|
glDisable(GL_NORMALIZE);
|
|
normalize_Status = GL_FALSE;
|
|
|
|
for (i = 0; i < (int)(sizeof(clipplane_Status) / sizeof(GLboolean)); i++) {
|
|
//glDisable(GL_CLIP_PLANE0+i);
|
|
clipplane_Status[i] = GL_FALSE;
|
|
}
|
|
|
|
if (GL_version >= 30) {
|
|
for (i = 0; i < (int)(sizeof(clipdistance_Status) / sizeof(GLboolean)); i++) {
|
|
//glDisable(GL_CLIP_DISTANCE0+i);
|
|
clipdistance_Status[i] = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
Assert( GL_max_lights > 0 );
|
|
light_Status = (GLboolean*) vm_malloc(GL_max_lights * sizeof(GLboolean));
|
|
|
|
for (i = 0; i < GL_max_lights; i++) {
|
|
glDisable(GL_LIGHT0+i);
|
|
light_Status[i] = GL_FALSE;
|
|
}
|
|
|
|
glDepthMask(GL_FALSE);
|
|
depthmask_Status = GL_FALSE;
|
|
|
|
glDisable(GL_LIGHTING);
|
|
lighting_Status = GL_FALSE;
|
|
|
|
glFrontFace(GL_CCW);
|
|
frontface_Value = GL_CCW;
|
|
|
|
glCullFace(GL_BACK);
|
|
cullface_Value = GL_BACK;
|
|
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
blendfunc_Value[0] = GL_ONE;
|
|
blendfunc_Value[1] = GL_ZERO;
|
|
|
|
glDepthFunc(GL_LESS);
|
|
depthfunc_Value = GL_LESS;
|
|
|
|
Current_alpha_blend_mode = ALPHA_BLEND_NONE;
|
|
Current_zbuffer_type = ZBUFFER_TYPE_READ;
|
|
|
|
red_Status = 255;
|
|
blue_Status = 255;
|
|
green_Status = 255;
|
|
alpha_Status = 255;
|
|
color_invalid = true;
|
|
}
|
|
|
|
GLboolean opengl_state::Lighting(GLint state)
|
|
{
|
|
GLboolean save_state = lighting_Status;
|
|
|
|
if ( !((state == -1) || (state == lighting_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_LIGHTING);
|
|
lighting_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_LIGHTING);
|
|
lighting_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::Fog(GLint state)
|
|
{
|
|
GLboolean save_state = fog_Status;
|
|
|
|
if ( !((state == -1) || (state == fog_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_FOG);
|
|
fog_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_FOG);
|
|
fog_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::Blend(GLint state)
|
|
{
|
|
GLboolean save_state = blend_Status;
|
|
|
|
if ( !((state == -1) || (state == blend_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_BLEND);
|
|
blend_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_BLEND);
|
|
blend_Status = GL_FALSE;
|
|
}
|
|
|
|
Current_alpha_blend_mode = (gr_alpha_blend)(-1);
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::AlphaTest(GLint state)
|
|
{
|
|
GLboolean save_state = alphatest_Status;
|
|
|
|
if ( !((state == -1) || (state == alphatest_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_ALPHA_TEST);
|
|
alphatest_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_ALPHA_TEST);
|
|
alphatest_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::DepthTest(GLint state)
|
|
{
|
|
GLboolean save_state = depthtest_Status;
|
|
|
|
if ( !((state == -1) || (state == depthtest_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_DEPTH_TEST);
|
|
depthtest_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_DEPTH_TEST);
|
|
depthtest_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::ScissorTest(GLint state)
|
|
{
|
|
GLboolean save_state = scissortest_Status;
|
|
|
|
if ( !((state == -1) || (state == scissortest_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_SCISSOR_TEST);
|
|
scissortest_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_SCISSOR_TEST);
|
|
scissortest_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::StencilTest(GLint state)
|
|
{
|
|
GLboolean save_state = stenciltest_Status;
|
|
|
|
if ( !((state == -1) || (state == stenciltest_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_STENCIL_TEST);
|
|
stenciltest_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_STENCIL_TEST);
|
|
stenciltest_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::CullFace(GLint state)
|
|
{
|
|
GLboolean save_state = cullface_Status;
|
|
|
|
if ( !((state == -1) || (state == cullface_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_CULL_FACE);
|
|
cullface_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_CULL_FACE);
|
|
cullface_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
void opengl_state::SetPolygonMode(GLenum face, GLenum mode)
|
|
{
|
|
if ( polygon_mode_Face != face || polygon_mode_Mode != mode ) {
|
|
glPolygonMode(face, mode);
|
|
|
|
polygon_mode_Face = face;
|
|
polygon_mode_Mode = mode;
|
|
}
|
|
}
|
|
|
|
void opengl_state::SetPolygonOffset(GLfloat factor, GLfloat units)
|
|
{
|
|
if ( polygon_offset_Factor != factor || polygon_offset_Unit != units) {
|
|
glPolygonOffset(factor, units);
|
|
|
|
polygon_offset_Factor = factor;
|
|
polygon_offset_Unit = units;
|
|
}
|
|
}
|
|
|
|
GLboolean opengl_state::PolygonOffsetFill(GLint state)
|
|
{
|
|
GLboolean save_state = polygonoffsetfill_Status;
|
|
|
|
if ( !((state == -1) || (state == polygonoffsetfill_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
polygonoffsetfill_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
polygonoffsetfill_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::Normalize(GLint state)
|
|
{
|
|
GLboolean save_state = normalize_Status;
|
|
|
|
if ( !((state == -1) || (state == normalize_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_NORMALIZE);
|
|
normalize_Status = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_NORMALIZE);
|
|
normalize_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::Light(GLint num, GLint state)
|
|
{
|
|
Assert( (light_Status != NULL) && (num >= 0) && (num < GL_max_lights) );
|
|
|
|
GLboolean save_state = light_Status[num];
|
|
|
|
if ( !((state == -1) || (state == light_Status[num])) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_LIGHT0+num);
|
|
light_Status[num] = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_LIGHT0+num);
|
|
light_Status[num] = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::ClipPlane(GLint num, GLint state)
|
|
{
|
|
Assert( (num >= 0) || (num < (int)(sizeof(clipplane_Status) / sizeof(GLboolean))) );
|
|
|
|
GLboolean save_state = clipplane_Status[num];
|
|
|
|
if ( !((state == -1) || (state == clipplane_Status[num])) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glEnable(GL_CLIP_PLANE0+num);
|
|
clipplane_Status[num] = GL_TRUE;
|
|
} else {
|
|
glDisable(GL_CLIP_PLANE0+num);
|
|
clipplane_Status[num] = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::ClipDistance(GLint num, GLint state)
|
|
{
|
|
Assert( (num >= 0) || (num < (int)(sizeof(clipdistance_Status) / sizeof(GLboolean))) || GL_version >= 30 );
|
|
|
|
GLboolean save_state = clipdistance_Status[num];
|
|
|
|
if ( !((state == -1) || (state == clipdistance_Status[num])) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
//glEnable(GL_CLIP_DISTANCE0+num);
|
|
clipdistance_Status[num] = GL_TRUE;
|
|
} else {
|
|
//glDisable(GL_CLIP_DISTANCE0+num);
|
|
clipdistance_Status[num] = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::DepthMask(GLint state)
|
|
{
|
|
GLboolean save_state = depthmask_Status;
|
|
|
|
if ( !((state == -1) || (state == depthmask_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glDepthMask(GL_TRUE);
|
|
depthmask_Status = GL_TRUE;
|
|
} else {
|
|
glDepthMask(GL_FALSE);
|
|
depthmask_Status = GL_FALSE;
|
|
}
|
|
|
|
Current_zbuffer_type = (gr_zbuffer_type)(-1);
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
GLboolean opengl_state::ColorMask(GLint state)
|
|
{
|
|
GLboolean save_state = colormask_Status;
|
|
|
|
if ( !((state == -1) || (state == colormask_Status)) ) {
|
|
if (state) {
|
|
Assert( state == GL_TRUE );
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
colormask_Status = GL_TRUE;
|
|
} else {
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
colormask_Status = GL_FALSE;
|
|
}
|
|
}
|
|
|
|
return save_state;
|
|
}
|
|
|
|
void opengl_state::SetTextureSource(gr_texture_source ts)
|
|
{
|
|
if (ts == Texture.Current_texture_source) {
|
|
return;
|
|
}
|
|
|
|
switch (ts) {
|
|
case TEXTURE_SOURCE_DECAL:
|
|
GL_state.Texture.SetActiveUnit();
|
|
GL_state.Texture.SetEnvMode(GL_MODULATE);
|
|
break;
|
|
|
|
case TEXTURE_SOURCE_NO_FILTERING:
|
|
GL_state.Texture.SetActiveUnit();
|
|
GL_state.Texture.SetEnvMode(GL_MODULATE);
|
|
break;
|
|
|
|
case TEXTURE_SOURCE_NONE:
|
|
GL_state.Texture.DisableAll();
|
|
break;
|
|
|
|
default:
|
|
Int3();
|
|
break;
|
|
}
|
|
|
|
Texture.Current_texture_source = ts;
|
|
}
|
|
|
|
void opengl_state::SetAlphaBlendMode(gr_alpha_blend ab)
|
|
{
|
|
if (ab == Current_alpha_blend_mode) {
|
|
return;
|
|
}
|
|
|
|
switch (ab) {
|
|
case ALPHA_BLEND_ALPHA_BLEND_ALPHA:
|
|
GL_state.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
break;
|
|
|
|
case ALPHA_BLEND_NONE:
|
|
GL_state.BlendFunc(GL_ONE, GL_ZERO);
|
|
break;
|
|
|
|
case ALPHA_BLEND_ADDITIVE:
|
|
GL_state.BlendFunc(GL_ONE, GL_ONE);
|
|
break;
|
|
|
|
case ALPHA_BLEND_ALPHA_ADDITIVE:
|
|
GL_state.BlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
break;
|
|
|
|
case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR:
|
|
GL_state.BlendFunc(/*GL_SRC_COLOR*/GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
|
|
break;
|
|
|
|
case ALPHA_BLEND_PREMULTIPLIED:
|
|
GL_state.BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GL_state.Blend( (ab == ALPHA_BLEND_NONE) ? GL_FALSE : GL_TRUE );
|
|
|
|
Current_alpha_blend_mode = ab;
|
|
}
|
|
|
|
void opengl_state::SetZbufferType(gr_zbuffer_type zt)
|
|
{
|
|
if (zt == Current_zbuffer_type) {
|
|
return;
|
|
}
|
|
|
|
switch (zt) {
|
|
case ZBUFFER_TYPE_NONE:
|
|
GL_state.DepthFunc(GL_ALWAYS);
|
|
GL_state.DepthMask(GL_FALSE);
|
|
break;
|
|
|
|
case ZBUFFER_TYPE_READ:
|
|
GL_state.DepthFunc(GL_LESS);
|
|
GL_state.DepthMask(GL_FALSE);
|
|
break;
|
|
|
|
case ZBUFFER_TYPE_WRITE:
|
|
GL_state.DepthFunc(GL_ALWAYS);
|
|
GL_state.DepthMask(GL_TRUE);
|
|
break;
|
|
|
|
case ZBUFFER_TYPE_FULL:
|
|
GL_state.DepthFunc(GL_LESS);
|
|
GL_state.DepthMask(GL_TRUE);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GL_state.DepthTest( (zt == ZBUFFER_TYPE_NONE) ? GL_FALSE : GL_TRUE );
|
|
|
|
Current_zbuffer_type = zt;
|
|
}
|
|
|
|
void opengl_state::SetStencilType(gr_stencil_type st)
|
|
{
|
|
if (st == Current_stencil_type) {
|
|
return;
|
|
}
|
|
|
|
switch (st) {
|
|
case STENCIL_TYPE_NONE:
|
|
glStencilFunc( GL_NEVER, 1, 0xFFFF );
|
|
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
|
break;
|
|
|
|
case STENCIL_TYPE_READ:
|
|
glStencilFunc( GL_NOTEQUAL, 1, 0XFFFF );
|
|
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
|
|
break;
|
|
|
|
case STENCIL_TYPE_WRITE:
|
|
glStencilFunc( GL_ALWAYS, 1, 0xFFFF );
|
|
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GL_state.StencilTest( (st == STENCIL_TYPE_NONE) ? GL_FALSE : GL_TRUE );
|
|
|
|
Current_stencil_type = st;
|
|
}
|
|
|
|
opengl_array_state::~opengl_array_state()
|
|
{
|
|
if ( client_texture_units != NULL ) {
|
|
vm_free(client_texture_units);
|
|
}
|
|
}
|
|
|
|
void opengl_array_state::init(GLuint n_units)
|
|
{
|
|
Assert( n_units > 0 );
|
|
client_texture_units = (opengl_client_texture_unit*) vm_malloc(n_units * sizeof(opengl_client_texture_unit));
|
|
num_client_texture_units = n_units;
|
|
active_client_texture_unit = 0;
|
|
|
|
for (unsigned int i = 0; i < num_client_texture_units; i++) {
|
|
client_texture_units[i].pointer = 0;
|
|
client_texture_units[i].size = 4;
|
|
client_texture_units[i].status = GL_FALSE;
|
|
client_texture_units[i].stride = 0;
|
|
client_texture_units[i].type = GL_FLOAT;
|
|
client_texture_units[i].buffer = 0;
|
|
client_texture_units[i].reset_ptr = false;
|
|
client_texture_units[i].used_for_draw = false;
|
|
}
|
|
|
|
color_array_Buffer = 0;
|
|
color_array_Status = GL_FALSE;
|
|
color_array_size = 4;
|
|
color_array_type = GL_FLOAT;
|
|
color_array_stride = 0;
|
|
color_array_pointer = 0;
|
|
color_array_reset_ptr = false;
|
|
color_array_used_for_draw = false;
|
|
|
|
normal_array_Buffer = 0;
|
|
normal_array_Status = GL_FALSE;
|
|
normal_array_Type = GL_FLOAT;
|
|
normal_array_Stride = 0;
|
|
normal_array_Pointer = 0;
|
|
normal_array_reset_ptr = false;
|
|
normal_array_used_for_draw = false;
|
|
|
|
vertex_array_Buffer = 0;
|
|
vertex_array_Status = GL_FALSE;
|
|
vertex_array_Size = 4;
|
|
vertex_array_Type = GL_FLOAT;
|
|
vertex_array_Stride = 0;
|
|
vertex_array_Pointer = 0;
|
|
vertex_array_reset_ptr = false;
|
|
vertex_array_used_for_draw = false;
|
|
|
|
array_buffer = 0;
|
|
element_array_buffer = 0;
|
|
texture_array_buffer = 0;
|
|
uniform_buffer = 0;
|
|
}
|
|
|
|
void opengl_array_state::SetActiveClientUnit(GLuint id)
|
|
{
|
|
if ( id >= num_client_texture_units ) {
|
|
Int3();
|
|
id = 0;
|
|
}
|
|
|
|
if ( active_client_texture_unit == id ) {
|
|
return;
|
|
}
|
|
|
|
glClientActiveTexture(GL_TEXTURE0 + id);
|
|
|
|
active_client_texture_unit = id;
|
|
}
|
|
|
|
void opengl_array_state::EnableClientTexture()
|
|
{
|
|
client_texture_units[active_client_texture_unit].used_for_draw = true;
|
|
|
|
if ( client_texture_units[active_client_texture_unit].status == GL_TRUE ) {
|
|
return;
|
|
}
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
client_texture_units[active_client_texture_unit].status = GL_TRUE;
|
|
}
|
|
|
|
void opengl_array_state::DisableClientTexture()
|
|
{
|
|
if ( client_texture_units[active_client_texture_unit].status == GL_FALSE ) {
|
|
return;
|
|
}
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
client_texture_units[active_client_texture_unit].status = GL_FALSE;
|
|
}
|
|
|
|
void opengl_array_state::TexPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
|
|
{
|
|
opengl_client_texture_unit *ct_unit = &client_texture_units[active_client_texture_unit];
|
|
|
|
if (
|
|
!ct_unit->reset_ptr
|
|
&& ct_unit->pointer == pointer
|
|
&& ct_unit->size == size
|
|
&& ct_unit->type == type
|
|
&& ct_unit->stride == stride
|
|
&& ct_unit->buffer == array_buffer
|
|
) {
|
|
return;
|
|
}
|
|
|
|
glTexCoordPointer(size, type, stride, pointer);
|
|
|
|
ct_unit->size = size;
|
|
ct_unit->type = type;
|
|
ct_unit->stride = stride;
|
|
ct_unit->pointer = pointer;
|
|
ct_unit->buffer = array_buffer;
|
|
ct_unit->reset_ptr = false;
|
|
}
|
|
|
|
void opengl_array_state::EnableClientColor()
|
|
{
|
|
color_array_used_for_draw = true;
|
|
|
|
if ( color_array_Status == GL_TRUE ) {
|
|
return;
|
|
}
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
color_array_Status = GL_TRUE;
|
|
}
|
|
|
|
void opengl_array_state::DisableClientColor()
|
|
{
|
|
if ( color_array_Status == GL_FALSE ) {
|
|
return;
|
|
}
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
color_array_Status = GL_FALSE;
|
|
}
|
|
|
|
void opengl_array_state::ColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
|
|
{
|
|
if (
|
|
!color_array_reset_ptr
|
|
&& color_array_size == size
|
|
&& color_array_type == type
|
|
&& color_array_stride == stride
|
|
&& color_array_pointer == pointer
|
|
&& color_array_Buffer == array_buffer
|
|
) {
|
|
return;
|
|
}
|
|
|
|
glColorPointer(size, type, stride, pointer);
|
|
|
|
color_array_size = size;
|
|
color_array_type = type;
|
|
color_array_stride = stride;
|
|
color_array_pointer = pointer;
|
|
color_array_Buffer = array_buffer;
|
|
color_array_reset_ptr = false;
|
|
}
|
|
|
|
void opengl_array_state::EnableClientNormal()
|
|
{
|
|
normal_array_used_for_draw = true;
|
|
|
|
if ( normal_array_Status == GL_TRUE ) {
|
|
return;
|
|
}
|
|
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
|
|
normal_array_Status = GL_TRUE;
|
|
}
|
|
|
|
void opengl_array_state::DisableClientNormal()
|
|
{
|
|
if ( normal_array_Status == GL_FALSE ) {
|
|
return;
|
|
}
|
|
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
normal_array_Status = GL_FALSE;
|
|
}
|
|
|
|
void opengl_array_state::NormalPointer(GLenum type, GLsizei stride, GLvoid *pointer)
|
|
{
|
|
if (
|
|
!normal_array_reset_ptr
|
|
&& normal_array_Type == type
|
|
&& normal_array_Stride == stride
|
|
&& normal_array_Pointer == pointer
|
|
&& normal_array_Buffer == array_buffer
|
|
) {
|
|
return;
|
|
}
|
|
|
|
glNormalPointer(type, stride, pointer);
|
|
|
|
normal_array_Type = type;
|
|
normal_array_Stride = stride;
|
|
normal_array_Pointer = pointer;
|
|
normal_array_Buffer = array_buffer;
|
|
normal_array_reset_ptr = false;
|
|
}
|
|
|
|
void opengl_array_state::EnableClientVertex()
|
|
{
|
|
vertex_array_used_for_draw = true;
|
|
|
|
if ( vertex_array_Status == GL_TRUE ) {
|
|
return;
|
|
}
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
vertex_array_Status = GL_TRUE;
|
|
}
|
|
|
|
void opengl_array_state::DisableClientVertex()
|
|
{
|
|
if ( vertex_array_Status == GL_FALSE ) {
|
|
return;
|
|
}
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
vertex_array_Status = GL_FALSE;
|
|
}
|
|
|
|
void opengl_array_state::VertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
|
|
{
|
|
if (
|
|
!vertex_array_reset_ptr
|
|
&& vertex_array_Size == size
|
|
&& vertex_array_Type == type
|
|
&& vertex_array_Stride == stride
|
|
&& vertex_array_Pointer == pointer
|
|
&& vertex_array_Buffer == array_buffer
|
|
) {
|
|
return;
|
|
}
|
|
|
|
glVertexPointer(size, type, stride, pointer);
|
|
|
|
vertex_array_Size = size;
|
|
vertex_array_Type = type;
|
|
vertex_array_Stride = stride;
|
|
vertex_array_Pointer = pointer;
|
|
vertex_array_Buffer = array_buffer;
|
|
vertex_array_reset_ptr = false;
|
|
}
|
|
|
|
void opengl_array_state::EnableVertexAttrib(GLuint index)
|
|
{
|
|
opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
|
|
|
|
va_unit->used_for_draw = true;
|
|
|
|
if ( va_unit->status_init && va_unit->status == GL_TRUE ) {
|
|
return;
|
|
}
|
|
|
|
glEnableVertexAttribArray(index);
|
|
va_unit->status = GL_TRUE;
|
|
va_unit->status_init = true;
|
|
}
|
|
|
|
void opengl_array_state::DisableVertexAttrib(GLuint index)
|
|
{
|
|
opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
|
|
|
|
if ( va_unit->status_init && va_unit->status == GL_FALSE ) {
|
|
return;
|
|
}
|
|
|
|
glDisableVertexAttribArray(index);
|
|
va_unit->status = GL_FALSE;
|
|
va_unit->status_init = true;
|
|
}
|
|
|
|
void opengl_array_state::VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer)
|
|
{
|
|
opengl_vertex_attrib_unit *va_unit = &vertex_attrib_units[index];
|
|
|
|
if (
|
|
!va_unit->reset_ptr
|
|
&& va_unit->ptr_init
|
|
&& va_unit->normalized == normalized
|
|
&& va_unit->pointer == pointer
|
|
&& va_unit->size == size
|
|
&& va_unit->stride == stride
|
|
&& va_unit->type == type
|
|
&& va_unit->buffer == array_buffer
|
|
) {
|
|
return;
|
|
}
|
|
|
|
glVertexAttribPointer(index, size, type, normalized, stride, pointer);
|
|
|
|
va_unit->normalized = normalized;
|
|
va_unit->pointer = pointer;
|
|
va_unit->size = size;
|
|
va_unit->stride = stride;
|
|
va_unit->type = type;
|
|
va_unit->buffer = array_buffer;
|
|
va_unit->reset_ptr = false;
|
|
|
|
va_unit->ptr_init = true;
|
|
}
|
|
|
|
void opengl_array_state::BindPointersBegin()
|
|
{
|
|
// set all available client states to not used
|
|
vertex_array_used_for_draw = false;
|
|
color_array_used_for_draw = false;
|
|
normal_array_used_for_draw = false;
|
|
|
|
for (unsigned int i = 0; i < num_client_texture_units; i++) {
|
|
client_texture_units[i].used_for_draw = false;
|
|
}
|
|
|
|
SCP_map<GLuint, opengl_vertex_attrib_unit>::iterator it;
|
|
|
|
for (it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it) {
|
|
it->second.used_for_draw = false;
|
|
}
|
|
}
|
|
|
|
void opengl_array_state::BindPointersEnd()
|
|
{
|
|
// any client states not used, disable them
|
|
if ( !vertex_array_used_for_draw ) DisableClientVertex();
|
|
if ( !color_array_used_for_draw ) DisableClientColor();
|
|
if ( !normal_array_used_for_draw ) DisableClientNormal();
|
|
|
|
for (unsigned int i = 0; i < num_client_texture_units; i++) {
|
|
if ( !client_texture_units[i].used_for_draw ) {
|
|
SetActiveClientUnit(i);
|
|
DisableClientTexture();
|
|
}
|
|
}
|
|
|
|
SCP_map<GLuint, opengl_vertex_attrib_unit>::iterator it;
|
|
|
|
for (it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it) {
|
|
if ( !it->second.used_for_draw ) DisableVertexAttrib(it->first);
|
|
}
|
|
}
|
|
|
|
void opengl_array_state::BindArrayBuffer(GLuint id)
|
|
{
|
|
if ( array_buffer == id ) {
|
|
return;
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, id);
|
|
|
|
array_buffer = id;
|
|
|
|
vertex_array_reset_ptr = true;
|
|
color_array_reset_ptr = true;
|
|
normal_array_reset_ptr = true;
|
|
|
|
for (unsigned int i = 0; i < num_client_texture_units; i++) {
|
|
client_texture_units[i].reset_ptr = true;
|
|
}
|
|
|
|
SCP_map<GLuint,opengl_vertex_attrib_unit>::iterator it;
|
|
|
|
for ( it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it ) {
|
|
it->second.reset_ptr = true;
|
|
}
|
|
}
|
|
|
|
void opengl_array_state::BindElementBuffer(GLuint id)
|
|
{
|
|
if ( element_array_buffer == id ) {
|
|
return;
|
|
}
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
|
|
|
|
element_array_buffer = id;
|
|
}
|
|
|
|
void opengl_array_state::BindTextureBuffer(GLuint id)
|
|
{
|
|
if ( !GLAD_GL_ARB_texture_buffer_object ) {
|
|
return;
|
|
}
|
|
|
|
if ( texture_array_buffer == id ) {
|
|
return;
|
|
}
|
|
|
|
glBindBuffer(GL_TEXTURE_BUFFER_ARB, id);
|
|
|
|
texture_array_buffer = id;
|
|
}
|
|
|
|
void opengl_array_state::BindUniformBufferBindingIndex(GLuint id, GLuint index)
|
|
{
|
|
if ( !GLAD_GL_ARB_uniform_buffer_object ) {
|
|
return;
|
|
}
|
|
|
|
if ( uniform_buffer_index_bindings[index] == id ) {
|
|
return;
|
|
}
|
|
|
|
glBindBufferBaseEXT(GL_UNIFORM_BUFFER, index, id);
|
|
|
|
uniform_buffer_index_bindings[index] = id;
|
|
}
|
|
|
|
void opengl_array_state::BindUniformBuffer(GLuint id)
|
|
{
|
|
if ( !GLAD_GL_ARB_uniform_buffer_object ) {
|
|
return;
|
|
}
|
|
|
|
if ( uniform_buffer == id ) {
|
|
return;
|
|
}
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, id);
|
|
|
|
uniform_buffer = id;
|
|
}
|
|
|
|
opengl_uniform_state::opengl_uniform_state()
|
|
{
|
|
}
|
|
|
|
int opengl_uniform_state::findUniform(const SCP_string &name)
|
|
{
|
|
SCP_map<SCP_string, int>::iterator iter;
|
|
|
|
iter = uniform_lookup.find(name);
|
|
|
|
if ( iter == uniform_lookup.end() ) {
|
|
return -1;
|
|
} else {
|
|
return iter->second;
|
|
}
|
|
}
|
|
|
|
void opengl_uniform_state::setUniformi(const SCP_string &name, const int val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::INT ) {
|
|
if ( uniform_data_ints[bind_info->index] == val ) {
|
|
return;
|
|
}
|
|
|
|
uniform_data_ints[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
uniform_data_ints.push_back(val);
|
|
|
|
uniform_bind new_bind;
|
|
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_ints.size() - 1;
|
|
new_bind.type = uniform_bind::INT;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniform1i(opengl_shader_get_uniform(name.c_str()), val);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniformf(const SCP_string &name, const float val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::FLOAT ) {
|
|
if ( fl_equal(uniform_data_floats[bind_info->index], val) ) {
|
|
return;
|
|
}
|
|
|
|
uniform_data_floats[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
uniform_data_floats.push_back(val);
|
|
|
|
uniform_bind new_bind;
|
|
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_floats.size() - 1;
|
|
new_bind.type = uniform_bind::FLOAT;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniform1f(opengl_shader_get_uniform(name.c_str()), val);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform2f(const SCP_string &name, const float x, const float y)
|
|
{
|
|
vec2d temp;
|
|
|
|
temp.x = x;
|
|
temp.y = y;
|
|
|
|
setUniform2f(name, temp);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform2f(const SCP_string &name, const vec2d &val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0 ) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::VEC2 ) {
|
|
if ( vm_vec_equal(uniform_data_vec2d[bind_info->index], val) ) {
|
|
return;
|
|
}
|
|
|
|
uniform_data_vec2d[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
uniform_data_vec2d.push_back(val);
|
|
|
|
uniform_bind new_bind;
|
|
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_vec2d.size() - 1;
|
|
new_bind.type = uniform_bind::VEC2;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniform2f(opengl_shader_get_uniform(name.c_str()), val.x, val.y);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform3f(const SCP_string &name, const float x, const float y, const float z)
|
|
{
|
|
vec3d temp;
|
|
|
|
temp.xyz.x = x;
|
|
temp.xyz.y = y;
|
|
temp.xyz.z = z;
|
|
|
|
setUniform3f(name, temp);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform3f(const SCP_string &name, const vec3d &val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0 ) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::VEC3 ) {
|
|
if ( vm_vec_equal(uniform_data_vec3d[bind_info->index], val) ) {
|
|
return;
|
|
}
|
|
|
|
uniform_data_vec3d[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
uniform_data_vec3d.push_back(val);
|
|
|
|
uniform_bind new_bind;
|
|
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_vec3d.size() - 1;
|
|
new_bind.type = uniform_bind::VEC3;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniform3f(opengl_shader_get_uniform(name.c_str()), val.a1d[0], val.a1d[1], val.a1d[2]);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform4f(const SCP_string &name, const float x, const float y, const float z, const float w)
|
|
{
|
|
vec4 temp;
|
|
|
|
temp.xyzw.x = x;
|
|
temp.xyzw.y = y;
|
|
temp.xyzw.z = z;
|
|
temp.xyzw.w = w;
|
|
|
|
setUniform4f(name, temp);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniform4f(const SCP_string &name, const vec4 &val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0 ) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::VEC4 ) {
|
|
if ( vm_vec_equal(uniform_data_vec4[bind_info->index], val) ) {
|
|
// if the values are close enough, pass.
|
|
return;
|
|
}
|
|
|
|
uniform_data_vec4[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
uniform_data_vec4.push_back(val);
|
|
|
|
uniform_bind new_bind;
|
|
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_vec4.size() - 1;
|
|
new_bind.type = uniform_bind::VEC4;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniform4f(opengl_shader_get_uniform(name.c_str()), val.a1d[0], val.a1d[1], val.a1d[2], val.a1d[3]);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniformMatrix4f(const SCP_string &name, const matrix4 &val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::MATRIX4 && bind_info->count == 1 ) {
|
|
if ( vm_matrix_equal(uniform_data_matrix4[bind_info->index], val) ) {
|
|
return;
|
|
}
|
|
|
|
uniform_data_matrix4[bind_info->index] = val;
|
|
resident = true;
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
//matrix_uniform_data[num_matrix_uniforms] = val;
|
|
//memcpy(&(matrix_uniform_data[num_matrix_uniforms]), &val, sizeof(matrix4));
|
|
uniform_data_matrix4.push_back(val);
|
|
// num_matrix_uniforms += 1;
|
|
|
|
uniform_bind new_bind;
|
|
new_bind.count = 1;
|
|
new_bind.index = uniform_data_matrix4.size() - 1;
|
|
// new_bind.index = num_matrix_uniforms - 1;
|
|
new_bind.type = uniform_bind::MATRIX4;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniformMatrix4fv(opengl_shader_get_uniform(name.c_str()), 1, GL_FALSE, (const GLfloat*)&val);
|
|
}
|
|
|
|
void opengl_uniform_state::setUniformMatrix4fv(const SCP_string &name, const int count, const matrix4 *val)
|
|
{
|
|
int uniform_index = findUniform(name);
|
|
bool resident = false;
|
|
|
|
if ( uniform_index >= 0) {
|
|
Assert( (size_t)uniform_index < uniforms.size() );
|
|
|
|
uniform_bind *bind_info = &uniforms[uniform_index];
|
|
|
|
if ( bind_info->type == uniform_bind::MATRIX4 && bind_info->count == count ) {
|
|
bool equal = true;
|
|
|
|
// if the values are close enough, pass.
|
|
for ( int i = 0; i < count; ++i ) {
|
|
if ( !vm_matrix_equal(val[i], uniform_data_matrix4[bind_info->index+i]) ) {
|
|
equal = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( equal ) {
|
|
return;
|
|
}
|
|
|
|
resident = true;
|
|
for ( int i = 0; i < count; ++i ) {
|
|
uniform_data_matrix4[bind_info->index+i] = val[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !resident ) {
|
|
// uniform doesn't exist in our previous uniform block so queue this new value
|
|
for ( int i = 0; i < count; ++i ) {
|
|
uniform_data_matrix4.push_back(val[i]);
|
|
}
|
|
|
|
uniform_bind new_bind;
|
|
new_bind.count = count;
|
|
new_bind.index = uniform_data_matrix4.size() - count;
|
|
// new_bind.index = num_matrix_uniforms - count;
|
|
new_bind.type = uniform_bind::MATRIX4;
|
|
new_bind.name = name;
|
|
|
|
uniforms.push_back(new_bind);
|
|
|
|
uniform_lookup[name] = uniforms.size()-1;
|
|
}
|
|
|
|
glUniformMatrix4fv(opengl_shader_get_uniform(name.c_str()), count, GL_FALSE, (const GLfloat*)val);
|
|
}
|
|
|
|
void opengl_uniform_state::reset()
|
|
{
|
|
uniforms.clear();
|
|
|
|
uniform_data_ints.clear();
|
|
uniform_data_floats.clear();
|
|
uniform_data_vec2d.clear();
|
|
uniform_data_vec3d.clear();
|
|
uniform_data_vec4.clear();
|
|
uniform_data_matrix4.clear();
|
|
|
|
uniform_lookup.clear();
|
|
}
|
|
|
|
void gr_opengl_clear_states()
|
|
{
|
|
GL_state.Texture.DisableAll();
|
|
|
|
gr_zbias(0);
|
|
gr_zbuffer_set(ZBUFFER_TYPE_READ);
|
|
gr_set_cull(0);
|
|
gr_set_fill_mode(GR_FILL_MODE_SOLID);
|
|
gr_reset_lighting();
|
|
gr_set_lighting(false, false);
|
|
|
|
opengl_shader_set_current();
|
|
}
|
|
|
|
void opengl_setup_render_states(int &r, int &g, int &b, int &alpha, int &tmap_type, int flags, int is_scaler)
|
|
{
|
|
gr_texture_source texture_source = (gr_texture_source)(-1);
|
|
gr_alpha_blend alpha_blend = (gr_alpha_blend)(-1);
|
|
gr_zbuffer_type zbuffer_type = (gr_zbuffer_type)(-1);
|
|
|
|
if (gr_zbuffering) {
|
|
if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) ) {
|
|
zbuffer_type = ZBUFFER_TYPE_READ;
|
|
} else {
|
|
zbuffer_type = ZBUFFER_TYPE_FULL;
|
|
}
|
|
} else {
|
|
zbuffer_type = ZBUFFER_TYPE_NONE;
|
|
}
|
|
|
|
tmap_type = TCACHE_TYPE_NORMAL;
|
|
|
|
if (flags & TMAP_FLAG_TEXTURED) {
|
|
r = g = b = 255;
|
|
} else {
|
|
r = gr_screen.current_color.red;
|
|
g = gr_screen.current_color.green;
|
|
b = gr_screen.current_color.blue;
|
|
}
|
|
|
|
if (flags & TMAP_FLAG_BW_TEXTURE) {
|
|
r = gr_screen.current_color.red;
|
|
g = gr_screen.current_color.green;
|
|
b = gr_screen.current_color.blue;
|
|
}
|
|
|
|
if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER ) {
|
|
if ( (gr_screen.current_bitmap >= 0) && bm_has_alpha_channel(gr_screen.current_bitmap) ) {
|
|
tmap_type = TCACHE_TYPE_XPARENT;
|
|
|
|
alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
|
|
|
|
// Blend with screen pixel using src*alpha+dst
|
|
float factor = gr_screen.current_alpha;
|
|
|
|
if (factor >= 1.0f) {
|
|
alpha = 255;
|
|
} else {
|
|
alpha = fl2i(gr_screen.current_alpha*255.0f);
|
|
}
|
|
} else {
|
|
tmap_type = TCACHE_TYPE_NORMAL;
|
|
alpha_blend = ALPHA_BLEND_ADDITIVE; // ALPHA_BLEND_ALPHA_ADDITIVE;
|
|
|
|
// Blend with screen pixel using src*alpha+dst
|
|
float factor = gr_screen.current_alpha;
|
|
|
|
alpha = 255;
|
|
|
|
if (factor < 1.0f) {
|
|
r = fl2i(r * gr_screen.current_alpha);
|
|
g = fl2i(g * gr_screen.current_alpha);
|
|
b = fl2i(b * gr_screen.current_alpha);
|
|
}
|
|
}
|
|
} else {
|
|
alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
|
|
alpha = fl2i(gr_screen.current_alpha * 255.0f);
|
|
}
|
|
|
|
|
|
if (flags & TMAP_FLAG_TEXTURED) {
|
|
// use nonfiltered textures for interface graphics
|
|
if (flags & TMAP_FLAG_INTERFACE) {
|
|
tmap_type = TCACHE_TYPE_INTERFACE;
|
|
texture_source = TEXTURE_SOURCE_NO_FILTERING;
|
|
} else {
|
|
texture_source = TEXTURE_SOURCE_DECAL;
|
|
}
|
|
} else {
|
|
texture_source = TEXTURE_SOURCE_NONE;
|
|
}
|
|
|
|
GL_state.SetTextureSource(texture_source);
|
|
GL_state.SetAlphaBlendMode(alpha_blend);
|
|
GL_state.SetZbufferType(zbuffer_type);
|
|
}
|