forked from 0ad/0ad
# Initial GLSL rendering support
This was SVN commit r10978.
This commit is contained in:
parent
8ca59d418d
commit
adbd7633dd
@ -52,6 +52,9 @@ force_s3tc_enable = true
|
||||
; but will reduce performance and features when a modern graphics card is available.
|
||||
renderpath = default
|
||||
|
||||
; Prefer GLSL shaders over ARB shaders (not recommended)
|
||||
preferglsl = false
|
||||
|
||||
; Adjusts how OpenGL calculates mipmap level of detail. 0.0f is the default (blurry) value.
|
||||
; Lower values sharpen/extend, and higher values blur/decrease. Clamped at -3.0 to 3.0.
|
||||
; -1.0 to -1.5 recommended for good results.
|
||||
|
14
binaries/data/mods/public/shaders/effects/model_normal.xml
Normal file
14
binaries/data/mods/public/shaders/effects/model_normal.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="model_common_arb"/>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="model_common_glsl"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="model_common_instancing_arb"/>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="model_common_instancing_glsl"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
54
binaries/data/mods/public/shaders/model_common.fs
Normal file
54
binaries/data/mods/public/shaders/model_common.fs
Normal file
@ -0,0 +1,54 @@
|
||||
uniform sampler2D baseTex;
|
||||
uniform sampler2DShadow shadowTex;
|
||||
uniform sampler2D losTex;
|
||||
uniform vec3 objectColor;
|
||||
uniform vec3 shadingColor;
|
||||
uniform vec3 ambient;
|
||||
uniform vec4 shadowOffsets1;
|
||||
uniform vec4 shadowOffsets2;
|
||||
|
||||
varying vec3 v_lighting;
|
||||
varying vec2 v_tex;
|
||||
varying vec4 v_shadow;
|
||||
varying vec2 v_los;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex = texture2D(baseTex, v_tex);
|
||||
|
||||
#ifdef USE_TRANSPARENT
|
||||
gl_FragColor.a = tex.a;
|
||||
#else
|
||||
gl_FragColor.a = 1.0;
|
||||
#endif
|
||||
|
||||
vec3 color = tex.rgb;
|
||||
|
||||
// Apply player-coloring based on texture alpha
|
||||
#ifdef USE_OBJECTCOLOR
|
||||
color *= mix(objectColor, 1.0, tex.a);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHADOW
|
||||
#ifdef USE_SHADOW_PCF
|
||||
float shadow = (
|
||||
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.xy, v_shadow.z)).a +
|
||||
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.zw, v_shadow.z)).a +
|
||||
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.xy, v_shadow.z)).a +
|
||||
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a
|
||||
) * 0.25;
|
||||
#else
|
||||
float shadow = shadow2D(shadowTex, v_shadow).a;
|
||||
#endif
|
||||
#else
|
||||
float shadow = 1.0;
|
||||
#endif
|
||||
|
||||
color *= v_lighting * shadow + ambient;
|
||||
|
||||
color *= texture2D(losTex, v_los).a;
|
||||
|
||||
color *= shadingColor;
|
||||
|
||||
gl_FragColor.rgb = color;
|
||||
}
|
28
binaries/data/mods/public/shaders/model_common.vs
Normal file
28
binaries/data/mods/public/shaders/model_common.vs
Normal file
@ -0,0 +1,28 @@
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunColor;
|
||||
uniform vec2 losTransform;
|
||||
uniform mat4 shadowTransform;
|
||||
uniform mat4 instancingTransform;
|
||||
|
||||
varying vec3 v_lighting;
|
||||
varying vec2 v_tex;
|
||||
varying vec4 v_shadow;
|
||||
varying vec2 v_los;
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef USE_INSTANCING
|
||||
vec4 position = instancingTransform * gl_Vertex;
|
||||
vec3 normal = instancingTransform * vec4(gl_Normal, 0.0);
|
||||
#else
|
||||
vec4 position = gl_Vertex;
|
||||
vec3 normal = gl_Normal;
|
||||
#endif
|
||||
|
||||
gl_Position = gl_ModelViewProjectionMatrix * position;
|
||||
|
||||
v_lighting = max(0.0, dot(normal, -sunDir)) * sunColor;
|
||||
v_tex = gl_MultiTexCoord0.xy;
|
||||
v_shadow = shadowTransform * position;
|
||||
v_los = position.xz * losTransform.x + losTransform.y;
|
||||
}
|
26
binaries/data/mods/public/shaders/model_common_glsl.xml
Normal file
26
binaries/data/mods/public/shaders/model_common_glsl.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="glsl">
|
||||
|
||||
<vertex file="model_common.vs">
|
||||
<uniform name="sunDir" type="vec3"/>
|
||||
<uniform name="sunColor" type="vec3"/>
|
||||
<uniform name="losTransform" type="vec2"/>
|
||||
<uniform name="shadowTransform" type="mat4"/>
|
||||
<stream name="pos"/>
|
||||
<stream name="normal"/>
|
||||
<stream name="uv0"/>
|
||||
</vertex>
|
||||
|
||||
<fragment file="model_common.fs">
|
||||
<uniform name="baseTex" type="sampler2D"/>
|
||||
<uniform name="shadowTex" type="sampler2DShadow"/>
|
||||
<uniform name="losTex" type="sampler2D"/>
|
||||
|
||||
<uniform name="objectColor" type="vec3"/>
|
||||
<uniform name="shadingColor" type="vec3"/>
|
||||
<uniform name="ambient" type="vec3"/>
|
||||
<uniform name="shadowOffsets1" type="vec4"/>
|
||||
<uniform name="shadowOffsets2" type="vec4"/>
|
||||
</fragment>
|
||||
|
||||
</program>
|
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<program type="glsl">
|
||||
|
||||
<define name="USE_INSTANCING" value="1"/>
|
||||
|
||||
<vertex file="model_common.vs">
|
||||
<uniform name="sunDir" type="vec3"/>
|
||||
<uniform name="sunColor" type="vec3"/>
|
||||
<uniform name="losTransform" type="vec2"/>
|
||||
<uniform name="shadowTransform" type="mat4"/>
|
||||
<uniform name="instancingTransform" type="mat4"/>
|
||||
<stream name="pos"/>
|
||||
<stream name="normal"/>
|
||||
<stream name="uv0"/>
|
||||
</vertex>
|
||||
|
||||
<fragment file="model_common.fs">
|
||||
<uniform name="baseTex" type="sampler2D"/>
|
||||
<uniform name="shadowTex" type="sampler2DShadow"/>
|
||||
<uniform name="losTex" type="sampler2D"/>
|
||||
|
||||
<uniform name="objectColor" type="vec3"/>
|
||||
<uniform name="shadingColor" type="vec3"/>
|
||||
<uniform name="ambient" type="vec3"/>
|
||||
<uniform name="shadowOffsets1" type="vec4"/>
|
||||
<uniform name="shadowOffsets2" type="vec4"/>
|
||||
</fragment>
|
||||
|
||||
</program>
|
@ -2,13 +2,6 @@
|
||||
<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
||||
<start>
|
||||
<element name="program">
|
||||
<attribute name="type">
|
||||
<choice>
|
||||
<value>arb</value>
|
||||
<value>glsl</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
|
||||
<zeroOrMore>
|
||||
<element name="define">
|
||||
<attribute name="name"><text/></attribute>
|
||||
@ -16,43 +9,67 @@
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
|
||||
<element name="vertex">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<choice>
|
||||
<ref name="uniformContent"/>
|
||||
<element name="attrib">
|
||||
<attribute name="name"><text/></attribute>
|
||||
<attribute name="loc"><data type="integer"/></attribute>
|
||||
</element>
|
||||
<element name="stream">
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>pos</value>
|
||||
<value>normal</value>
|
||||
<value>color</value>
|
||||
<value>uv0</value>
|
||||
<value>uv1</value>
|
||||
<value>uv2</value>
|
||||
<value>uv3</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</element>
|
||||
</choice>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
<choice>
|
||||
<group>
|
||||
<attribute name="type">
|
||||
<value>arb</value>
|
||||
</attribute>
|
||||
|
||||
<element name="fragment">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<ref name="uniformContent"/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
<element name="vertex">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<choice>
|
||||
<ref name="uniformContentARB"/>
|
||||
<element name="attrib">
|
||||
<attribute name="name"><text/></attribute>
|
||||
<attribute name="loc"><data type="integer"/></attribute>
|
||||
</element>
|
||||
<ref name="streamContent"/>
|
||||
</choice>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
|
||||
<element name="fragment">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<ref name="uniformContentARB"/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<attribute name="type">
|
||||
<value>glsl</value>
|
||||
</attribute>
|
||||
|
||||
<element name="vertex">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<choice>
|
||||
<ref name="uniformContentGLSL"/>
|
||||
<element name="attrib">
|
||||
<attribute name="name"><text/></attribute>
|
||||
<attribute name="loc"><data type="integer"/></attribute>
|
||||
</element>
|
||||
<ref name="streamContent"/>
|
||||
</choice>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
|
||||
<element name="fragment">
|
||||
<attribute name="file"><text/></attribute>
|
||||
<zeroOrMore>
|
||||
<ref name="uniformContentGLSL"/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
|
||||
</group>
|
||||
</choice>
|
||||
</element>
|
||||
|
||||
</start>
|
||||
|
||||
<define name="uniformContent">
|
||||
<define name="uniformContentARB">
|
||||
<element name="uniform">
|
||||
<attribute name="name"><text/></attribute>
|
||||
<attribute name="loc"><data type="integer"/></attribute>
|
||||
@ -73,4 +90,40 @@
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="uniformContentGLSL">
|
||||
<element name="uniform">
|
||||
<attribute name="name"><text/></attribute>
|
||||
<attribute name="type">
|
||||
<choice>
|
||||
<value>float</value>
|
||||
<value>vec2</value>
|
||||
<value>vec3</value>
|
||||
<value>vec4</value>
|
||||
<value>mat2</value>
|
||||
<value>mat3</value>
|
||||
<value>mat4</value>
|
||||
<value>sampler2D</value>
|
||||
<value>sampler2DShadow</value>
|
||||
<value>samplerCube</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="streamContent">
|
||||
<element name="stream">
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>pos</value>
|
||||
<value>normal</value>
|
||||
<value>color</value>
|
||||
<value>uv0</value>
|
||||
<value>uv1</value>
|
||||
<value>uv2</value>
|
||||
<value>uv3</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
</grammar>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "ShaderManager.h"
|
||||
|
||||
#include "graphics/ShaderTechnique.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/utf8.h"
|
||||
#include "ps/CLogger.h"
|
||||
@ -30,6 +31,14 @@
|
||||
|
||||
TIMER_ADD_CLIENT(tc_ShaderValidation);
|
||||
|
||||
struct revcompare2nd
|
||||
{
|
||||
template<typename S, typename T> bool operator()(const std::pair<S, T>& a, const std::pair<S, T>& b) const
|
||||
{
|
||||
return b.second < a.second;
|
||||
}
|
||||
};
|
||||
|
||||
CShaderManager::CShaderManager()
|
||||
{
|
||||
#if USE_SHADER_XML_VALIDATION
|
||||
@ -73,6 +82,21 @@ CShaderProgramPtr CShaderManager::LoadProgram(const char* name, const std::map<C
|
||||
return program;
|
||||
}
|
||||
|
||||
static GLenum GetGLSLType(const CStr type)
|
||||
{
|
||||
if (type == "float") return GL_FLOAT;
|
||||
if (type == "vec2") return GL_FLOAT_VEC2;
|
||||
if (type == "vec3") return GL_FLOAT_VEC3;
|
||||
if (type == "vec4") return GL_FLOAT_VEC4;
|
||||
if (type == "mat2") return GL_FLOAT_MAT2;
|
||||
if (type == "mat3") return GL_FLOAT_MAT3;
|
||||
if (type == "mat4") return GL_FLOAT_MAT4;
|
||||
if (type == "sampler2D") return GL_SAMPLER_2D;
|
||||
if (type == "sampler2DShadow") return GL_SAMPLER_2D;
|
||||
if (type == "samplerCube") return GL_SAMPLER_CUBE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CShaderManager::NewProgram(const char* name, const std::map<CStr, CStr>& baseDefines, CShaderProgramPtr& program)
|
||||
{
|
||||
PROFILE2("loading shader");
|
||||
@ -131,8 +155,9 @@ bool CShaderManager::NewProgram(const char* name, const std::map<CStr, CStr>& ba
|
||||
VfsPath vertexFile;
|
||||
VfsPath fragmentFile;
|
||||
std::map<CStr, CStr> defines = baseDefines;
|
||||
std::map<CStr, int> vertexUniforms;
|
||||
std::map<CStr, int> fragmentUniforms;
|
||||
std::map<CStr, int> arbVertexUniforms;
|
||||
std::map<CStr, int> arbFragmentUniforms;
|
||||
std::map<CStr, GLenum> glslUniforms;
|
||||
int streamFlags = 0;
|
||||
|
||||
XERO_ITER_EL(Root, Child)
|
||||
@ -149,7 +174,10 @@ bool CShaderManager::NewProgram(const char* name, const std::map<CStr, CStr>& ba
|
||||
{
|
||||
if (Param.GetNodeName() == el_uniform)
|
||||
{
|
||||
vertexUniforms[Param.GetAttributes().GetNamedItem(at_name)] = Param.GetAttributes().GetNamedItem(at_loc).ToInt();
|
||||
if (isGLSL)
|
||||
glslUniforms[Param.GetAttributes().GetNamedItem(at_name)] = GetGLSLType(Param.GetAttributes().GetNamedItem(at_type));
|
||||
else
|
||||
arbVertexUniforms[Param.GetAttributes().GetNamedItem(at_name)] = Param.GetAttributes().GetNamedItem(at_loc).ToInt();
|
||||
}
|
||||
else if (Param.GetNodeName() == el_stream)
|
||||
{
|
||||
@ -182,15 +210,21 @@ bool CShaderManager::NewProgram(const char* name, const std::map<CStr, CStr>& ba
|
||||
XERO_ITER_EL(Child, Param)
|
||||
{
|
||||
if (Param.GetNodeName() == el_uniform)
|
||||
fragmentUniforms[Param.GetAttributes().GetNamedItem(at_name)] = Param.GetAttributes().GetNamedItem(at_loc).ToInt();
|
||||
{
|
||||
if (isGLSL)
|
||||
glslUniforms[Param.GetAttributes().GetNamedItem(at_name)] = GetGLSLType(Param.GetAttributes().GetNamedItem(at_type));
|
||||
else
|
||||
arbFragmentUniforms[Param.GetAttributes().GetNamedItem(at_name)] = Param.GetAttributes().GetNamedItem(at_loc).ToInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add GLSL support
|
||||
ENSURE(!isGLSL);
|
||||
if (isGLSL)
|
||||
program = CShaderProgramPtr(CShaderProgram::ConstructGLSL(vertexFile, fragmentFile, defines, glslUniforms, streamFlags));
|
||||
else
|
||||
program = CShaderProgramPtr(CShaderProgram::ConstructARB(vertexFile, fragmentFile, defines, arbVertexUniforms, arbFragmentUniforms, streamFlags));
|
||||
|
||||
program = CShaderProgramPtr(CShaderProgram::ConstructARB(vertexFile, fragmentFile, defines, vertexUniforms, fragmentUniforms, streamFlags));
|
||||
program->Reload();
|
||||
|
||||
// m_HotloadFiles[xmlFilename].insert(program); // TODO: should reload somehow when the XML changes
|
||||
@ -200,6 +234,88 @@ bool CShaderManager::NewProgram(const char* name, const std::map<CStr, CStr>& ba
|
||||
return true;
|
||||
}
|
||||
|
||||
CShaderTechnique CShaderManager::LoadEffect(const char* name, const std::map<CStr, CStr>& baseDefines)
|
||||
{
|
||||
PROFILE2("loading effect");
|
||||
PROFILE2_ATTR("name: %s", name);
|
||||
|
||||
VfsPath xmlFilename = L"shaders/effects/" + wstring_from_utf8(name) + L".xml";
|
||||
|
||||
CXeromyces XeroFile;
|
||||
PSRETURN ret = XeroFile.Load(g_VFS, xmlFilename);
|
||||
if (ret != PSRETURN_OK)
|
||||
return CShaderTechnique();
|
||||
|
||||
// Define all the elements and attributes used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
|
||||
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
|
||||
EL(pass);
|
||||
EL(require);
|
||||
AT(shaders);
|
||||
AT(shader);
|
||||
#undef AT
|
||||
#undef EL
|
||||
|
||||
XMBElement Root = XeroFile.GetRoot();
|
||||
|
||||
// Find all the techniques that we can use, and their preference
|
||||
|
||||
std::vector<std::pair<XMBElement, int> > usableTechs;
|
||||
|
||||
XERO_ITER_EL(Root, Technique)
|
||||
{
|
||||
int preference = 0;
|
||||
bool isUsable = true;
|
||||
XERO_ITER_EL(Technique, Child)
|
||||
{
|
||||
if (Child.GetNodeName() == el_require)
|
||||
{
|
||||
if (Child.GetAttributes().GetNamedItem(at_shaders) == "arb")
|
||||
{
|
||||
if (!g_Renderer.GetCapabilities().m_ARBProgram)
|
||||
isUsable = false;
|
||||
}
|
||||
else if (Child.GetAttributes().GetNamedItem(at_shaders) == "glsl")
|
||||
{
|
||||
if (!g_Renderer.GetCapabilities().m_VertexShader || !g_Renderer.GetCapabilities().m_FragmentShader)
|
||||
isUsable = false;
|
||||
|
||||
if (g_Renderer.m_Options.m_PreferGLSL)
|
||||
preference += 100;
|
||||
else
|
||||
preference -= 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isUsable)
|
||||
usableTechs.push_back(std::make_pair(Technique, preference));
|
||||
}
|
||||
|
||||
if (usableTechs.empty())
|
||||
{
|
||||
debug_warn(L"Can't find a usable technique");
|
||||
return CShaderTechnique();
|
||||
}
|
||||
|
||||
// Sort by preference, tie-break on order of specification
|
||||
std::stable_sort(usableTechs.begin(), usableTechs.end(), revcompare2nd());
|
||||
|
||||
CShaderTechnique tech;
|
||||
|
||||
XERO_ITER_EL(usableTechs[0].first, Child)
|
||||
{
|
||||
if (Child.GetNodeName() == el_pass)
|
||||
{
|
||||
CShaderProgramPtr shader = LoadProgram(Child.GetAttributes().GetNamedItem(at_shader).c_str(), baseDefines);
|
||||
CShaderPass pass(shader);
|
||||
tech.AddPass(pass);
|
||||
}
|
||||
}
|
||||
|
||||
return tech;
|
||||
}
|
||||
|
||||
/*static*/ Status CShaderManager::ReloadChangedFileCB(void* param, const VfsPath& path)
|
||||
{
|
||||
return static_cast<CShaderManager*>(param)->ReloadChangedFile(path);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -31,6 +31,8 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
class CShaderTechnique;
|
||||
|
||||
/**
|
||||
* Shader manager: loads and caches shader programs.
|
||||
*/
|
||||
@ -48,6 +50,15 @@ public:
|
||||
*/
|
||||
CShaderProgramPtr LoadProgram(const char* name, const std::map<CStr, CStr>& defines);
|
||||
|
||||
/**
|
||||
* Load a shader effect.
|
||||
* Effects can be implemented via many techniques; this returns the best usable technique.
|
||||
* @param name name of effect XML specification (file is loaded from shaders/effects/${name}.xml)
|
||||
* @param defines key/value set of preprocessor definitions
|
||||
* @return loaded technique, or empty technique on error
|
||||
*/
|
||||
CShaderTechnique LoadEffect(const char* name, const std::map<CStr, CStr>& defines);
|
||||
|
||||
private:
|
||||
bool NewProgram(const char* name, const std::map<CStr, CStr>& defines, CShaderProgramPtr& program);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -51,26 +51,6 @@ public:
|
||||
pglDeleteProgramsARB(1, &m_FragmentProgram);
|
||||
}
|
||||
|
||||
CStr Preprocess(CPreprocessor& preprocessor, const CStr& input)
|
||||
{
|
||||
size_t len = 0;
|
||||
char* output = preprocessor.Parse(input.c_str(), input.size(), len);
|
||||
|
||||
if (!output)
|
||||
{
|
||||
LOGERROR(L"Shader preprocessing failed");
|
||||
return "";
|
||||
}
|
||||
|
||||
CStr ret(output, len);
|
||||
|
||||
// Free output if it's not inside the source string
|
||||
if (!(output >= input.c_str() && output < input.c_str() + input.size()))
|
||||
free(output);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Compile(GLuint target, const char* targetName, GLuint program, const VfsPath& file, const CStr& code)
|
||||
{
|
||||
ogl_WarnIfError();
|
||||
@ -199,29 +179,29 @@ public:
|
||||
|
||||
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
||||
{
|
||||
if (id.vertex != -1)
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.vertex, v0, v1, v2, v3);
|
||||
if (id.first != -1)
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first, v0, v1, v2, v3);
|
||||
|
||||
if (id.fragment != -1)
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.fragment, v0, v1, v2, v3);
|
||||
if (id.second != -1)
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
virtual void Uniform(Binding id, const CMatrix3D& v)
|
||||
{
|
||||
if (id.vertex != -1)
|
||||
if (id.first != -1)
|
||||
{
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.vertex+0, v._11, v._12, v._13, v._14);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.vertex+1, v._21, v._22, v._23, v._24);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.vertex+2, v._31, v._32, v._33, v._34);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.vertex+3, v._41, v._42, v._43, v._44);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+0, v._11, v._12, v._13, v._14);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+1, v._21, v._22, v._23, v._24);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+2, v._31, v._32, v._33, v._34);
|
||||
pglProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+3, v._41, v._42, v._43, v._44);
|
||||
}
|
||||
|
||||
if (id.fragment != -1)
|
||||
if (id.second != -1)
|
||||
{
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.fragment+0, v._11, v._12, v._13, v._14);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.fragment+1, v._21, v._22, v._23, v._24);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.fragment+2, v._31, v._32, v._33, v._34);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.fragment+3, v._41, v._42, v._43, v._44);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+0, v._11, v._12, v._13, v._14);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+1, v._21, v._22, v._23, v._24);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+2, v._31, v._32, v._33, v._34);
|
||||
pglProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+3, v._41, v._42, v._43, v._44);
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,6 +218,273 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class CShaderProgramGLSL : public CShaderProgram
|
||||
{
|
||||
public:
|
||||
CShaderProgramGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile,
|
||||
const std::map<CStr, CStr>& defines,
|
||||
const std::map<CStr, GLenum>& uniformTypes,
|
||||
int streamflags) :
|
||||
CShaderProgram(streamflags),
|
||||
m_VertexFile(vertexFile), m_FragmentFile(fragmentFile),
|
||||
m_Defines(defines),
|
||||
m_UniformTypes(uniformTypes)
|
||||
{
|
||||
m_Program = 0;
|
||||
m_VertexShader = pglCreateShaderObjectARB(GL_VERTEX_SHADER);
|
||||
m_FragmentShader = pglCreateShaderObjectARB(GL_FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
~CShaderProgramGLSL()
|
||||
{
|
||||
Unload();
|
||||
|
||||
pglDeleteShader(m_VertexShader);
|
||||
pglDeleteShader(m_FragmentShader);
|
||||
}
|
||||
|
||||
bool Compile(GLuint shader, const VfsPath& file, const CStr& code)
|
||||
{
|
||||
ogl_WarnIfError();
|
||||
|
||||
const char* code_string = code.c_str();
|
||||
GLint code_length = code.length();
|
||||
pglShaderSourceARB(shader, 1, &code_string, &code_length);
|
||||
|
||||
pglCompileShaderARB(shader);
|
||||
|
||||
GLint ok = 0;
|
||||
pglGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
GLint length = 0;
|
||||
pglGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
// Apparently sometimes GL_INFO_LOG_LENGTH is incorrectly reported as 0
|
||||
// (http://code.google.com/p/android/issues/detail?id=9953)
|
||||
if (length == 0)
|
||||
length = 4096;
|
||||
|
||||
char* infolog = new char[length];
|
||||
pglGetShaderInfoLog(shader, length, NULL, infolog);
|
||||
LOGERROR(L"Failed to compile shader '%ls':\n%hs", file.string().c_str(), infolog);
|
||||
delete[] infolog;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ogl_WarnIfError();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Link()
|
||||
{
|
||||
ENSURE(!m_Program);
|
||||
m_Program = pglCreateProgramObjectARB();
|
||||
|
||||
pglAttachObjectARB(m_Program, m_VertexShader);
|
||||
ogl_WarnIfError();
|
||||
pglAttachObjectARB(m_Program, m_FragmentShader);
|
||||
ogl_WarnIfError();
|
||||
|
||||
pglLinkProgramARB(m_Program);
|
||||
|
||||
GLint ok = 0;
|
||||
pglGetProgramiv(m_Program, GL_LINK_STATUS, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
GLint length = 0;
|
||||
pglGetProgramiv(m_Program, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
if (length == 0)
|
||||
length = 4096;
|
||||
|
||||
char* infolog = new char[length];
|
||||
pglGetProgramInfoLog(m_Program, length, NULL, infolog);
|
||||
LOGERROR(L"Failed to link program '%ls'+'%ls':\n%hs", m_VertexFile.string().c_str(), m_FragmentFile.string().c_str(), infolog);
|
||||
delete[] infolog;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ogl_WarnIfError();
|
||||
|
||||
m_UniformLocations.clear();
|
||||
m_Samplers.clear();
|
||||
|
||||
Bind();
|
||||
|
||||
for (std::map<CStr, GLenum>::iterator it = m_UniformTypes.begin(); it != m_UniformTypes.end(); ++it)
|
||||
{
|
||||
int loc = pglGetUniformLocationARB(m_Program, it->first.c_str());
|
||||
m_UniformLocations[it->first] = loc;
|
||||
|
||||
if (loc != -1)
|
||||
{
|
||||
// Assign in-use sampler uniforms to sequential texture units
|
||||
if (it->second == GL_SAMPLER_2D || it->second == GL_SAMPLER_CUBE)
|
||||
{
|
||||
int unit = (int)m_Samplers.size();
|
||||
m_Samplers[it->first].first = (it->second == GL_SAMPLER_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D);
|
||||
m_Samplers[it->first].second = unit;
|
||||
pglUniform1iARB(loc, unit); // link uniform to unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: verify that we're not using more samplers than is supported
|
||||
|
||||
Unbind();
|
||||
|
||||
ogl_WarnIfError();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Reload()
|
||||
{
|
||||
Unload();
|
||||
|
||||
CVFSFile vertexFile;
|
||||
if (vertexFile.Load(g_VFS, m_VertexFile) != PSRETURN_OK)
|
||||
return;
|
||||
|
||||
CVFSFile fragmentFile;
|
||||
if (fragmentFile.Load(g_VFS, m_FragmentFile) != PSRETURN_OK)
|
||||
return;
|
||||
|
||||
CPreprocessor preprocessor;
|
||||
for (std::map<CStr, CStr>::iterator it = m_Defines.begin(); it != m_Defines.end(); ++it)
|
||||
preprocessor.Define(it->first.c_str(), it->second.c_str());
|
||||
|
||||
CStr vertexCode = Preprocess(preprocessor, vertexFile.GetAsString());
|
||||
CStr fragmentCode = Preprocess(preprocessor, fragmentFile.GetAsString());
|
||||
|
||||
if (!Compile(m_VertexShader, m_VertexFile, vertexCode))
|
||||
return;
|
||||
|
||||
if (!Compile(m_FragmentShader, m_FragmentFile, fragmentCode))
|
||||
return;
|
||||
|
||||
if (!Link())
|
||||
return;
|
||||
|
||||
m_IsValid = true;
|
||||
}
|
||||
|
||||
void Unload()
|
||||
{
|
||||
m_IsValid = false;
|
||||
|
||||
if (m_Program)
|
||||
pglDeleteProgram(m_Program);
|
||||
m_Program = 0;
|
||||
|
||||
// The shader objects can be reused and don't need to be deleted here
|
||||
}
|
||||
|
||||
virtual void Bind()
|
||||
{
|
||||
pglUseProgramObjectARB(m_Program);
|
||||
}
|
||||
|
||||
virtual void Unbind()
|
||||
{
|
||||
pglUseProgramObjectARB(0);
|
||||
|
||||
// TODO: should unbind textures, probably
|
||||
}
|
||||
|
||||
int GetUniformLocation(uniform_id_t id)
|
||||
{
|
||||
std::map<CStr, int>::iterator it = m_UniformLocations.find(id);
|
||||
if (it == m_UniformLocations.end())
|
||||
return -1;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
virtual bool HasTexture(texture_id_t id)
|
||||
{
|
||||
if (GetUniformLocation(id) != -1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void BindTexture(texture_id_t id, Handle tex)
|
||||
{
|
||||
std::map<CStr, std::pair<GLenum, int> >::iterator it = m_Samplers.find(id);
|
||||
if (it == m_Samplers.end())
|
||||
return;
|
||||
|
||||
GLuint h;
|
||||
ogl_tex_get_texture_id(tex, &h);
|
||||
pglActiveTextureARB(GL_TEXTURE0 + it->second.second);
|
||||
glBindTexture(it->second.first, h);
|
||||
}
|
||||
|
||||
virtual void BindTexture(texture_id_t id, GLuint tex)
|
||||
{
|
||||
std::map<CStr, std::pair<GLenum, int> >::iterator it = m_Samplers.find(id);
|
||||
if (it == m_Samplers.end())
|
||||
return;
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0 + it->second.second);
|
||||
glBindTexture(it->second.first, tex);
|
||||
}
|
||||
|
||||
virtual Binding GetUniformBinding(uniform_id_t id)
|
||||
{
|
||||
int loc = GetUniformLocation(id);
|
||||
if (loc == -1)
|
||||
return Binding();
|
||||
else
|
||||
return Binding(loc, m_UniformTypes[id]);
|
||||
}
|
||||
|
||||
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
||||
{
|
||||
if (id.first != -1)
|
||||
{
|
||||
if (id.second == GL_FLOAT)
|
||||
pglUniform1fARB(id.first, v0);
|
||||
else if (id.second == GL_FLOAT_VEC2)
|
||||
pglUniform2fARB(id.first, v0, v1);
|
||||
else if (id.second == GL_FLOAT_VEC3)
|
||||
pglUniform3fARB(id.first, v0, v1, v2);
|
||||
else if (id.second == GL_FLOAT_VEC4)
|
||||
pglUniform4fARB(id.first, v0, v1, v2, v3);
|
||||
else
|
||||
LOGERROR(L"CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Uniform(Binding id, const CMatrix3D& v)
|
||||
{
|
||||
if (id.first != -1)
|
||||
{
|
||||
if (id.second == GL_FLOAT_MAT4)
|
||||
pglUniformMatrix4fvARB(id.first, 1, GL_FALSE, &v._11);
|
||||
else
|
||||
LOGERROR(L"CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
VfsPath m_VertexFile;
|
||||
VfsPath m_FragmentFile;
|
||||
std::map<CStr, CStr> m_Defines;
|
||||
|
||||
GLuint m_Program;
|
||||
GLuint m_VertexShader;
|
||||
GLuint m_FragmentShader;
|
||||
|
||||
std::map<CStr, GLenum> m_UniformTypes;
|
||||
std::map<CStr, int> m_UniformLocations;
|
||||
std::map<CStr, std::pair<GLenum, int> > m_Samplers; // texture target & unit chosen for each uniform sampler
|
||||
};
|
||||
|
||||
|
||||
|
||||
CShaderProgram::CShaderProgram(int streamflags)
|
||||
: m_IsValid(false), m_StreamFlags(streamflags)
|
||||
@ -252,6 +499,14 @@ CShaderProgram::CShaderProgram(int streamflags)
|
||||
return new CShaderProgramARB(vertexFile, fragmentFile, defines, vertexIndexes, fragmentIndexes, streamflags);
|
||||
}
|
||||
|
||||
/*static*/ CShaderProgram* CShaderProgram::ConstructGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile,
|
||||
const std::map<CStr, CStr>& defines,
|
||||
const std::map<CStr, GLenum>& uniformTypes,
|
||||
int streamflags)
|
||||
{
|
||||
return new CShaderProgramGLSL(vertexFile, fragmentFile, defines, uniformTypes, streamflags);
|
||||
}
|
||||
|
||||
bool CShaderProgram::IsValid() const
|
||||
{
|
||||
return m_IsValid;
|
||||
@ -311,3 +566,24 @@ void CShaderProgram::Uniform(uniform_id_t id, const CMatrix3D& v)
|
||||
{
|
||||
Uniform(GetUniformBinding(id), v);
|
||||
}
|
||||
|
||||
CStr CShaderProgram::Preprocess(CPreprocessor& preprocessor, const CStr& input)
|
||||
{
|
||||
size_t len = 0;
|
||||
char* output = preprocessor.Parse(input.c_str(), input.size(), len);
|
||||
|
||||
if (!output)
|
||||
{
|
||||
LOGERROR(L"Shader preprocessing failed");
|
||||
return "";
|
||||
}
|
||||
|
||||
CStr ret(output, len);
|
||||
|
||||
// Free output if it's not inside the source string
|
||||
if (!(output >= input.c_str() && output < input.c_str() + input.size()))
|
||||
free(output);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -28,6 +28,7 @@
|
||||
struct CColor;
|
||||
class CMatrix3D;
|
||||
class CVector3D;
|
||||
class CPreprocessor;
|
||||
|
||||
// Vertex data stream flags
|
||||
enum
|
||||
@ -68,6 +69,14 @@ public:
|
||||
const std::map<CStr, int>& vertexIndexes, const std::map<CStr, int>& fragmentIndexes,
|
||||
int streamflags);
|
||||
|
||||
/**
|
||||
* Construct based on GLSL vertex/fragment shader files.
|
||||
*/
|
||||
static CShaderProgram* ConstructGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile,
|
||||
const std::map<CStr, CStr>& defines,
|
||||
const std::map<CStr, GLenum>& uniformTypes,
|
||||
int streamflags);
|
||||
|
||||
/**
|
||||
* Construct an instance of a pre-defined fixed-function pipeline setup.
|
||||
*/
|
||||
@ -79,21 +88,25 @@ public:
|
||||
|
||||
/**
|
||||
* Represents a uniform attribute binding.
|
||||
* ARB shaders store vertex location in 'first', fragment location in 'second'.
|
||||
* GLSL shaders store uniform location in 'first', data type in 'second'.
|
||||
* FFP shaders store -1 in 'first', index in 'second'.
|
||||
* Non-existent bindings must store -1 in both.
|
||||
*/
|
||||
struct Binding
|
||||
{
|
||||
Binding(int v, int f) : vertex((i16)v), fragment((i16)f) { }
|
||||
Binding(int a, int b) : first(a), second(b) { }
|
||||
|
||||
Binding() : vertex(-1), fragment(-1) { }
|
||||
Binding() : first(-1), second(-1) { }
|
||||
|
||||
/**
|
||||
* Returns whether this uniform attribute is active in the shader.
|
||||
* If not then there's no point calling Uniform() to set its value.
|
||||
*/
|
||||
bool Active() { return vertex != -1 || fragment != -1; }
|
||||
bool Active() { return first != -1 || second != -1; }
|
||||
|
||||
i16 vertex;
|
||||
i16 fragment;
|
||||
int first;
|
||||
int second;
|
||||
};
|
||||
|
||||
virtual ~CShaderProgram() { }
|
||||
@ -157,6 +170,8 @@ public:
|
||||
protected:
|
||||
CShaderProgram(int streamflags);
|
||||
|
||||
CStr Preprocess(CPreprocessor& preprocessor, const CStr& input);
|
||||
|
||||
bool m_IsValid;
|
||||
int m_StreamFlags;
|
||||
};
|
||||
|
@ -124,7 +124,7 @@ public:
|
||||
|
||||
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3)
|
||||
{
|
||||
if (id.fragment == ID_losTransform)
|
||||
if (id.second == ID_losTransform)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE2);
|
||||
GLfloat texgenS1[4] = { v0, 0, 0, v1 };
|
||||
@ -132,7 +132,7 @@ public:
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
|
||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
|
||||
}
|
||||
else if (id.fragment == ID_objectColor)
|
||||
else if (id.second == ID_objectColor)
|
||||
{
|
||||
float c[] = { v0, v1, v2, v3 };
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -111,6 +111,10 @@ void CShaderPass::DepthFunc(GLenum func)
|
||||
}
|
||||
|
||||
|
||||
CShaderTechnique::CShaderTechnique()
|
||||
{
|
||||
}
|
||||
|
||||
CShaderTechnique::CShaderTechnique(const CShaderPass& pass)
|
||||
{
|
||||
m_Passes.push_back(pass);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -79,6 +79,7 @@ private:
|
||||
class CShaderTechnique
|
||||
{
|
||||
public:
|
||||
CShaderTechnique();
|
||||
CShaderTechnique(const CShaderPass& pass);
|
||||
void AddPass(const CShaderPass& pass);
|
||||
|
||||
|
@ -1074,6 +1074,13 @@ Status ogl_tex_bind(Handle ht, size_t unit)
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
Status ogl_tex_get_texture_id(Handle ht, GLuint* id)
|
||||
{
|
||||
*id = 0;
|
||||
H_DEREF(ht, OglTex, ot);
|
||||
*id = ot->id;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
// apply the specified transforms (as in tex_transform) to the image.
|
||||
// must be called before uploading (raises a warning if called afterwards).
|
||||
|
@ -432,6 +432,11 @@ extern Status ogl_tex_get_average_colour(Handle ht, u32* p);
|
||||
*/
|
||||
extern Status ogl_tex_bind(Handle ht, size_t unit = 0);
|
||||
|
||||
/**
|
||||
* Return the GL handle of the loaded texture in *id, or 0 on failure.
|
||||
*/
|
||||
extern Status ogl_tex_get_texture_id(Handle ht, GLuint* id);
|
||||
|
||||
/**
|
||||
* (partially) Transform pixel format of the texture.
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -36,6 +36,7 @@
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "maths/MathUtil.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/ConfigDB.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/Filesystem.h"
|
||||
@ -447,6 +448,10 @@ CRenderer::CRenderer()
|
||||
m_Options.m_ShadowAlphaFix = true;
|
||||
m_Options.m_ARBProgramShadow = true;
|
||||
m_Options.m_ShadowPCF = false;
|
||||
m_Options.m_PreferGLSL = false;
|
||||
|
||||
// TODO: be more consistent in use of the config system
|
||||
CFG_GET_USER_VAL("preferglsl", Bool, m_Options.m_PreferGLSL);
|
||||
|
||||
m_ShadowZBias = 0.02f;
|
||||
m_ShadowMapSize = 0;
|
||||
@ -565,12 +570,12 @@ void CRenderer::ReloadShaders()
|
||||
defTransparent["USE_TRANSPARENT"] = "1";
|
||||
|
||||
// TODO: it'd be nicer to load this technique from an XML file or something
|
||||
CShaderPass passTransparentOpaque(m->shaderManager.LoadProgram("model_common", defTransparent));
|
||||
CShaderPass passTransparentOpaque(m->shaderManager.LoadProgram("model_common_arb", defTransparent));
|
||||
passTransparentOpaque.AlphaFunc(GL_GREATER, 0.9375f);
|
||||
passTransparentOpaque.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
CShaderTechnique techTransparentOpaque(passTransparentOpaque);
|
||||
|
||||
CShaderPass passTransparentBlend(m->shaderManager.LoadProgram("model_common", defTransparent));
|
||||
CShaderPass passTransparentBlend(m->shaderManager.LoadProgram("model_common_arb", defTransparent));
|
||||
passTransparentBlend.AlphaFunc(GL_GREATER, 0.0f);
|
||||
passTransparentBlend.DepthFunc(GL_LESS);
|
||||
passTransparentBlend.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -597,15 +602,15 @@ void CRenderer::ReloadShaders()
|
||||
m->Model.ModShaderSolidTex = RenderModifierPtr(new ShaderRenderModifier(CShaderTechnique(m->shaderManager.LoadProgram(
|
||||
"solid_tex", defNull))));
|
||||
|
||||
m->Model.ModShaderNormal = LitRenderModifierPtr(new ShaderRenderModifier(CShaderTechnique(m->shaderManager.LoadProgram(
|
||||
"model_common", defBasic))));
|
||||
m->Model.ModShaderNormalInstancing = LitRenderModifierPtr(new ShaderRenderModifier(CShaderTechnique(m->shaderManager.LoadProgram(
|
||||
"model_common_instancing", defBasic))));
|
||||
m->Model.ModShaderNormal =
|
||||
LitRenderModifierPtr(new ShaderRenderModifier(m->shaderManager.LoadEffect("model_normal", defBasic)));
|
||||
m->Model.ModShaderNormalInstancing =
|
||||
LitRenderModifierPtr(new ShaderRenderModifier(m->shaderManager.LoadEffect("model_normal_instancing", defBasic)));
|
||||
|
||||
m->Model.ModShaderPlayer = LitRenderModifierPtr(new ShaderRenderModifier(CShaderTechnique(m->shaderManager.LoadProgram(
|
||||
"model_common", defColored))));
|
||||
m->Model.ModShaderPlayerInstancing = LitRenderModifierPtr(new ShaderRenderModifier(CShaderTechnique(m->shaderManager.LoadProgram(
|
||||
"model_common_instancing", defColored))));
|
||||
m->Model.ModShaderPlayer =
|
||||
LitRenderModifierPtr(new ShaderRenderModifier(m->shaderManager.LoadEffect("model_normal", defColored)));
|
||||
m->Model.ModShaderPlayerInstancing =
|
||||
LitRenderModifierPtr(new ShaderRenderModifier(m->shaderManager.LoadEffect("model_normal_instancing", defColored)));
|
||||
|
||||
m->Model.ModShaderTransparent = LitRenderModifierPtr(new ShaderRenderModifier(
|
||||
techTransparent));
|
||||
@ -2072,6 +2077,19 @@ void CRenderer::JSI_SetShadowPCF(JSContext* ctx, jsval newval)
|
||||
ReloadShaders();
|
||||
}
|
||||
|
||||
jsval CRenderer::JSI_GetPreferGLSL(JSContext*)
|
||||
{
|
||||
return ToJSVal(m_Options.m_PreferGLSL);
|
||||
}
|
||||
|
||||
void CRenderer::JSI_SetPreferGLSL(JSContext* ctx, jsval newval)
|
||||
{
|
||||
if (!ToPrimitive(ctx, newval, m_Options.m_PreferGLSL))
|
||||
return;
|
||||
|
||||
ReloadShaders();
|
||||
}
|
||||
|
||||
jsval CRenderer::JSI_GetSky(JSContext*)
|
||||
{
|
||||
return ToJSVal(m->skyManager.GetSkySet());
|
||||
@ -2097,6 +2115,7 @@ void CRenderer::ScriptingInit()
|
||||
AddProperty(L"depthTextureBits", &CRenderer::JSI_GetDepthTextureBits, &CRenderer::JSI_SetDepthTextureBits);
|
||||
AddProperty(L"shadowAlphaFix", &CRenderer::JSI_GetShadowAlphaFix, &CRenderer::JSI_SetShadowAlphaFix);
|
||||
AddProperty(L"shadowPCF", &CRenderer::JSI_GetShadowPCF, &CRenderer::JSI_SetShadowPCF);
|
||||
AddProperty(L"preferGLSL", &CRenderer::JSI_GetPreferGLSL, &CRenderer::JSI_SetPreferGLSL);
|
||||
AddProperty(L"skipSubmit", &CRenderer::m_SkipSubmit);
|
||||
AddProperty(L"skySet", &CRenderer::JSI_GetSky, &CRenderer::JSI_SetSky);
|
||||
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
bool m_ShadowAlphaFix;
|
||||
bool m_ARBProgramShadow;
|
||||
bool m_ShadowPCF;
|
||||
bool m_PreferGLSL;
|
||||
} m_Options;
|
||||
|
||||
struct Caps {
|
||||
@ -317,6 +318,8 @@ protected:
|
||||
void JSI_SetShadowAlphaFix(JSContext* ctx, jsval newval);
|
||||
jsval JSI_GetShadowPCF(JSContext*);
|
||||
void JSI_SetShadowPCF(JSContext* ctx, jsval newval);
|
||||
jsval JSI_GetPreferGLSL(JSContext*);
|
||||
void JSI_SetPreferGLSL(JSContext* ctx, jsval newval);
|
||||
jsval JSI_GetSky(JSContext*);
|
||||
void JSI_SetSky(JSContext* ctx, jsval newval);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user