This commit is contained in:
gl3nn
2014-01-18 01:07:32 +01:00
17 changed files with 431 additions and 286 deletions

62
INSTALL
View File

@@ -1,62 +0,0 @@
SUPERTUXKART INSTALLATION INSTRUCTIONS
======================================
Note : If you obtained this source code from github, you also need to download the game assets from sourceforge using SVN.
svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets
Place the stk-assets folder next to the source root stk-code folder.
See http://supertuxkart.sourceforge.net/Source_control for more information
Building STK on Linux
--------------------
First, make sure that you have the following packages installed:
* OpenGL (mesa)
* OpenAL (recommended: openal-soft-devel)
* Ogg (libogg-dev)
* Vorbis (libvorbis-dev)
* libcurl (libcurl-devel)
* libbluetooth (bluez-devel)
Ubuntu command :
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
Unpack the files from the tarball like this:
tar xzf supertuxkart-*.tar.gz
cd supertuxkart-*
where '*' is the version of SuperTuxkart you downloaded - eg 0.8.0. Then:
* Compile SuperTuxKart:
mkdir cmake_build
cd cmake_build
cmake ..
make VERBOSE=1 -j2
To create a debug version of STK, use:
cmake .. -DCMAKE_BUILD_TYPE=Debug
To test the compilation, supertuxkart can be run from the build
directory by ./bin/supertuxkart
To install the file, as root execute:
make install
The default install location is /usr/local, i.e. the data files will
be written to /usr/local/share/games/supertuxkart, the executable
will be copied to /usr/local/bin. To change the default installation
location, specify CMAKE_INSTALL_PREFIX when running cmake, e.g.:
cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk
Building STK on OS X
--------------------
See http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX
Building STK on Windows
-----------------------
See http://supertuxkart.sourceforge.net/How_to_build_the_Windows_version

71
INSTALL.md Normal file
View File

@@ -0,0 +1,71 @@
#SuperTuxKart Installation Instructions
Note : If you obtained this source code from github, you also need to download the game assets from sourceforge using SVN.
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
Place the `stk-assets` folder next to the source root `stk-code` folder.
See <http://supertuxkart.sourceforge.net/Source_control> for more information
##Building STK on Linux
First, make sure that you have the following packages installed:
* OpenGL (mesa)
* OpenAL (recommended: openal-soft-devel)
* Ogg (libogg-dev)
* Vorbis (libvorbis-dev)
* libcurl (libcurl-devel)
* libbluetooth (bluez-devel)
Ubuntu command:
```
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
```
Unpack the files from the tarball like this:
```
tar xzf supertuxkart-*.tar.gz
cd supertuxkart-*
```
where `*` is the version of SuperTuxkart you downloaded - eg `0.8.0`. Then:
Compile SuperTuxKart:
```
mkdir cmake_build
cd cmake_build
cmake ..
make VERBOSE=1 -j2
```
To create a debug version of STK, use:
`cmake .. -DCMAKE_BUILD_TYPE=Debug`
To test the compilation, supertuxkart can be run from the build
directory by ./bin/supertuxkart
To install the file, as root execute:
`make install`
The default install location is `/usr/local`, i.e. the data files will
be written to `/usr/local/share/games/supertuxkart`, the executable
will be copied to `/usr/local/bin`. To change the default installation
location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
`cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk`
##Building STK on OS X
See <http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX>
##Building STK on Windows
See <http://supertuxkart.sourceforge.net/How_to_build_the_Windows_version>

View File

@@ -1,10 +1,11 @@
#version 130
uniform sampler2D tex;
uniform vec2 res;
in vec2 uv;
void main()
{
vec2 coords = gl_FragCoord.xy / res;
vec2 coords = uv;
vec4 col = texture2D(tex, coords);
float alpha = col.a;

View File

@@ -1,10 +1,8 @@
#version 130
uniform sampler2D texture; //The texture
uniform sampler2D normalMap; //The bump-map
uniform sampler2D normalMap;
noperspective in vec3 tangent;
noperspective in vec3 bitangent;
noperspective in vec3 normal;
in vec2 uv;
void main()
@@ -13,15 +11,11 @@ void main()
vec3 TS_normal = 2.0 * texture2D (normalMap, uv).rgb - 1.0;
// Because of interpolation, we need to renormalize
vec3 Frag_tangent = normalize(tangent);
vec3 Frag_bitangent = normalize(cross(normal, tangent));
vec3 Frag_normal = cross(Frag_tangent, Frag_bitangent);
vec3 Frag_normal = normalize(cross(Frag_tangent, bitangent));
vec3 Frag_bitangent = cross(Frag_normal, Frag_tangent);
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent + TS_normal.z * Frag_normal;
vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal;
FragmentNormal = normalize(FragmentNormal);
gl_FragData[0] = texture2D (texture, uv);
gl_FragData[1] = vec4(0.5 * FragmentNormal + 0.5, gl_FragCoord.z);
gl_FragData[2] = vec4(0.);
gl_FragColor = vec4(0.5 * FragmentNormal + 0.5, gl_FragCoord.z);
}

View File

@@ -2,17 +2,19 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 TransposeInverseModelView;
in vec3 Position;
in vec2 Texcoord;
in vec3 Tangent;
in vec3 Bitangent;
noperspective out vec3 tangent;
noperspective out vec3 bitangent;
noperspective out vec3 normal;
out vec2 uv;
void main()
{
uv = gl_MultiTexCoord0.st;
normal = (TransposeInverseModelView * vec4(gl_Normal, 1.)).xyz;
tangent = (TransposeInverseModelView * gl_MultiTexCoord1).xyz;
bitangent = (TransposeInverseModelView * gl_MultiTexCoord2).xyz;
gl_Position = ModelViewProjectionMatrix * gl_Vertex;
uv = Texcoord;
tangent = (TransposeInverseModelView * vec4(Tangent, 1.)).xyz;
bitangent = (TransposeInverseModelView * vec4(Bitangent, 1.)).xyz;
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
}

View File

@@ -1,66 +1,66 @@
#version 130
uniform sampler2D normals_and_depth;
uniform mat4 invprojm;
uniform mat4 projm;
uniform vec4 samplePoints[16];
in vec2 uv;
const float strengh = 4.;
const float radius = .4f;
#define SAMPLES 16
const float invSamples = strengh / SAMPLES;
// Found here : http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
#version 130
uniform sampler2D normals_and_depth;
uniform mat4 invprojm;
uniform mat4 projm;
uniform vec4 samplePoints[16];
in vec2 uv;
const float strengh = 4.;
const float radius = .4f;
#define SAMPLES 16
const float invSamples = strengh / SAMPLES;
// Found here : http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
float rand(vec2 co)
{
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
void main(void)
{
vec4 cur = texture2D(normals_and_depth, uv);
float curdepth = texture2D(normals_and_depth, uv).a;
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
FragPos /= FragPos.w;
// get the normal of current fragment
vec3 norm = normalize(cur.xyz * vec3(2.0) - vec3(1.0));
// Workaround for nvidia and skyboxes
float len = dot(vec3(1.0), abs(cur.xyz));
if (len < 0.2 || curdepth > 0.99) discard;
// Make a tangent as random as possible
vec3 randvect;
randvect.x = rand(uv);
randvect.y = rand(vec2(randvect.x, FragPos.z));
randvect.z = rand(randvect.xy);
vec3 tangent = normalize(cross(norm, randvect));
vec3 bitangent = cross(norm, tangent);
float bl = 0.0;
for(int i = 0; i < SAMPLES; ++i) {
vec3 sampleDir = samplePoints[i].x * tangent + samplePoints[i].y * bitangent + samplePoints[i].z * norm;
sampleDir *= samplePoints[i].w;
vec4 samplePos = FragPos + radius * vec4(sampleDir, 0.0);
vec4 sampleProj = projm * samplePos;
sampleProj /= sampleProj.w;
bool isInsideTexture = (sampleProj.x > -1.) && (sampleProj.x < 1.) && (sampleProj.y > -1.) && (sampleProj.y < 1.);
// get the depth of the occluder fragment
float occluderFragmentDepth = texture2D(normals_and_depth, (sampleProj.xy * 0.5) + 0.5).a;
// Position of the occluder fragment in worldSpace
vec4 occluderPos = invprojm * vec4(sampleProj.xy, 2.0 * occluderFragmentDepth - 1.0, 1.0f);
occluderPos /= occluderPos.w;
bool isOccluded = isInsideTexture && (sampleProj.z > (2. * occluderFragmentDepth - 1.0)) && (distance(FragPos, occluderPos) < radius);
bl += isOccluded ? smoothstep(radius, 0, distance(samplePos, FragPos)) : 0.;
}
// output the result
float ao = 1.0 - bl * invSamples;
gl_FragColor = vec4(ao);
}
}
void main(void)
{
vec4 cur = texture2D(normals_and_depth, uv);
float curdepth = texture2D(normals_and_depth, uv).a;
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
FragPos /= FragPos.w;
// get the normal of current fragment
vec3 norm = normalize(cur.xyz * vec3(2.0) - vec3(1.0));
// Workaround for nvidia and skyboxes
float len = dot(vec3(1.0), abs(cur.xyz));
if (len < 0.2 || curdepth > 0.999) discard;
// Make a tangent as random as possible
vec3 randvect;
randvect.x = rand(uv);
randvect.y = rand(vec2(randvect.x, FragPos.z));
randvect.z = rand(randvect.xy);
vec3 tangent = normalize(cross(norm, randvect));
vec3 bitangent = cross(norm, tangent);
float bl = 0.0;
for(int i = 0; i < SAMPLES; ++i) {
vec3 sampleDir = samplePoints[i].x * tangent + samplePoints[i].y * bitangent + samplePoints[i].z * norm;
sampleDir *= samplePoints[i].w;
vec4 samplePos = FragPos + radius * vec4(sampleDir, 0.0);
vec4 sampleProj = projm * samplePos;
sampleProj /= sampleProj.w;
bool isInsideTexture = (sampleProj.x > -1.) && (sampleProj.x < 1.) && (sampleProj.y > -1.) && (sampleProj.y < 1.);
// get the depth of the occluder fragment
float occluderFragmentDepth = texture2D(normals_and_depth, (sampleProj.xy * 0.5) + 0.5).a;
// Position of the occluder fragment in worldSpace
vec4 occluderPos = invprojm * vec4(sampleProj.xy, 2.0 * occluderFragmentDepth - 1.0, 1.0f);
occluderPos /= occluderPos.w;
bool isOccluded = isInsideTexture && (sampleProj.z > (2. * occluderFragmentDepth - 1.0)) && (distance(FragPos, occluderPos) < radius);
bl += isOccluded ? smoothstep(radius, 0, distance(samplePos, FragPos)) : 0.;
}
// output the result
float ao = 1.0 - bl * invSamples;
gl_FragColor = vec4(ao);
}

View File

@@ -317,6 +317,21 @@ public:
m_color[2] = b;
}
float getRed() const
{
return m_color[0];
}
float getGreen() const
{
return m_color[1];
}
float getBlue() const
{
return m_color[2];
}
private:
float m_color[3];
};

View File

@@ -61,18 +61,6 @@ GlowNode::~GlowNode()
void GlowNode::render()
{
return;
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, AbsoluteTransformation);
drv->setMaterial(mat);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, ~0);
glEnable(GL_STENCIL_TEST);
drv->drawMeshBuffer(sphere->getMeshBuffer(0));
glDisable(GL_STENCIL_TEST);
}
void GlowNode::OnRegisterSceneNode()

View File

@@ -413,9 +413,12 @@ void IrrDriver::initDevice()
m_scene_manager = m_device->getSceneManager();
m_gui_env = m_device->getGUIEnvironment();
m_video_driver = m_device->getVideoDriver();
m_glsl = m_video_driver->queryFeature(video::EVDF_ARB_GLSL) &&
m_video_driver->queryFeature(video::EVDF_TEXTURE_NPOT) &&
UserConfigParams::m_pixel_shaders;
int GLMajorVersion;
glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion);
printf("OPENGL VERSION IS %d\n", GLMajorVersion);
m_glsl = (GLMajorVersion >= 3) && UserConfigParams::m_pixel_shaders;
// This remaps the window, so it has to be done before the clear to avoid flicker
m_device->setResizable(false);

View File

@@ -762,6 +762,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (irr_driver->isGLSL())
{
if (mb->getVertexType() != video::EVT_TANGENTS)
Log::error("material", "Requiring normal map without tangent enabled mesh");
ITexture* tex = irr_driver->getTexture(m_normal_map_tex);
if (m_is_heightmap)
{

View File

@@ -425,6 +425,22 @@ namespace PassThroughShader
}
}
namespace GlowShader
{
GLuint Program = 0;
GLuint uniform_tex;
GLuint vao = 0;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/glow.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
vao = createVAO(Program);
}
}
namespace SSAOShader
{
GLuint Program = 0;
@@ -771,6 +787,27 @@ void PostProcessing::renderPassThrough(ITexture *tex)
glDisable(GL_BLEND);
}
void PostProcessing::renderGlow(ITexture *tex)
{
if (!GlowShader::Program)
GlowShader::init();
glDisable(GL_DEPTH_TEST);
glUseProgram(GlowShader::Program);
glBindVertexArray(GlowShader::vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName());
glUniform1i(GlowShader::uniform_tex, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
void PostProcessing::renderSSAO(const core::matrix4 &invprojm, const core::matrix4 &projm)
{
@@ -787,6 +824,10 @@ void PostProcessing::renderSSAO(const core::matrix4 &invprojm, const core::matri
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, static_cast<irr::video::COpenGLTexture*>(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH))->getOpenGLTextureName());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glUniform1i(SSAOShader::uniform_normals_and_depth, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -890,15 +931,8 @@ void PostProcessing::render()
renderBloom(in);
}
// Do we have any forced bloom nodes? If so, draw them now
const std::vector<IrrDriver::BloomData> &blooms = irr_driver->getForcedBloom();
const u32 bloomsize = blooms.size();
if (!globalbloom && bloomsize)
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
if (globalbloom || bloomsize)
if (globalbloom)
{
// Clear the alpha to a suitable value, stencil
glClearColor(0, 0, 0, 0.1f);
@@ -909,86 +943,6 @@ void PostProcessing::render()
glClearColor(0, 0, 0, 0);
glColorMask(1, 1, 1, 1);
// The forced-bloom objects are drawn again, to know which pixels to pick.
// While it's more drawcalls, there's a cost to using four MRTs over three,
// and there shouldn't be many such objects in a track.
// The stencil is already in use for the glow. The alpha channel is best
// reserved for other use (specular, etc).
//
// They are drawn with depth and color writes off, giving 4x-8x drawing speed.
if (bloomsize)
{
const core::aabbox3df &cambox = camnode->
getViewFrustum()->
getBoundingBox();
irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_SOLID);
SOverrideMaterial &overridemat = drv->getOverrideMaterial();
overridemat.EnablePasses = ESNRP_SOLID;
overridemat.EnableFlags = EMF_MATERIAL_TYPE | EMF_ZWRITE_ENABLE | EMF_COLOR_MASK;
overridemat.Enabled = true;
overridemat.Material.MaterialType = irr_driver->getShader(ES_BLOOM_POWER);
overridemat.Material.ZWriteEnable = false;
overridemat.Material.ColorMask = ECP_ALPHA;
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, ~0);
glEnable(GL_STENCIL_TEST);
camnode->render();
for (u32 i = 0; i < bloomsize; i++)
{
scene::ISceneNode * const cur = blooms[i].node;
// Quick box-based culling
const core::aabbox3df nodebox = cur->getTransformedBoundingBox();
if (!nodebox.intersectsWithBox(cambox))
continue;
bloomcb->setPower(blooms[i].power);
cur->render();
}
// Second pass for transparents. No-op for solids.
irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_TRANSPARENT);
for (u32 i = 0; i < bloomsize; i++)
{
scene::ISceneNode * const cur = blooms[i].node;
// Quick box-based culling
const core::aabbox3df nodebox = cur->getTransformedBoundingBox();
if (!nodebox.intersectsWithBox(cambox))
continue;
bloomcb->setPower(blooms[i].power);
cur->render();
}
overridemat.Enabled = 0;
overridemat.EnablePasses = 0;
// Ok, we have the stencil; now use it to blit from color to bloom tex
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, ~0);
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, irr_driver->getRTT(RTT_COLOR));
// Just in case.
glColorMask(1, 1, 1, 0);
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), false, false);
m_material.ColorMask = ECP_RGB;
drawQuad(cam, m_material);
m_material.ColorMask = ECP_ALL;
glColorMask(1, 1, 1, 1);
glDisable(GL_STENCIL_TEST);
} // end forced bloom
// To half
drv->setRenderTarget(irr_driver->getRTT(RTT_HALF1), true, false);
renderPassThrough(irr_driver->getRTT(RTT_TMP3));

View File

@@ -88,6 +88,8 @@ public:
/** Render tex. Used for blit/texture resize */
void renderPassThrough(video::ITexture *tex);
void renderGlow(video::ITexture *tex);
/** Render the post-processed scene */
void render();

View File

@@ -213,12 +213,6 @@ void IrrDriver::renderGLSL(float dt)
// Used to cull glowing items & lights
const core::aabbox3df cambox = camnode->getViewFrustum()->getBoundingBox();
// Render anything glowing.
if (!m_mipviz && !m_wireframe)
{
//renderGlow(overridemat, glows, cambox, cam);
} // end glow
// Shadows
if (!m_mipviz && !m_wireframe && UserConfigParams::m_shadows &&
World::getWorld()->getTrack()->hasShadows())
@@ -236,6 +230,13 @@ void IrrDriver::renderGLSL(float dt)
m_scene_manager->drawAll(m_renderpass);
glDisable(GL_STENCIL_TEST);
// Render anything glowing.
if (!m_mipviz && !m_wireframe)
{
irr_driver->setPhase(2);
renderGlow(overridemat, glows, cambox, cam);
} // end glow
if (!bgnodes)
{
// If there are no BG nodes, it's more efficient to do the skybox here.
@@ -665,10 +666,13 @@ void IrrDriver::renderGlow(video::SOverrideMaterial &overridemat,
// Blur it
m_post_processing->renderGaussian6Blur(m_rtts->getRTT(RTT_QUARTER1), m_rtts->getRTT(RTT_QUARTER2), 4.f / UserConfigParams::m_width, 4.f / UserConfigParams::m_height);
// The glows will be rendered in the transparent phase
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, EBF_ONE_MINUS_SRC_ALPHA);
glStencilFunc(GL_EQUAL, 0, ~0);
glEnable(GL_STENCIL_TEST);
m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, false);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
m_post_processing->renderGlow(m_rtts->getRTT(RTT_QUARTER1));
glDisable(GL_STENCIL_TEST);
}

View File

@@ -3,9 +3,10 @@
#include <ISceneManager.h>
#include <IMaterialRenderer.h>
#include "config/user_config.hpp"
#include "graphics/callbacks.hpp"
static
GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_texcoord, GLuint attrib_normal, size_t stride)
GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_texcoord, GLuint attrib_normal, GLuint attrib_tangent, GLuint attrib_bitangent, size_t stride)
{
GLuint vao;
glGenVertexArrays(1, &vao);
@@ -16,11 +17,28 @@ GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_t
glEnableVertexAttribArray(attrib_texcoord);
if ((GLint)attrib_normal != -1)
glEnableVertexAttribArray(attrib_normal);
if ((GLint)attrib_tangent != -1)
glEnableVertexAttribArray(attrib_tangent);
if ((GLint)attrib_bitangent != -1)
glEnableVertexAttribArray(attrib_bitangent);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, stride, 0);
if ((GLint)attrib_texcoord != -1)
glVertexAttribPointer(attrib_texcoord, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 28);
if ((GLint)attrib_normal != -1)
glVertexAttribPointer(attrib_normal, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*) 12);
if ((GLint)attrib_tangent != -1)
{
assert(stride >= 48);
glVertexAttribPointer(attrib_tangent, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)36);
}
if ((GLint)attrib_bitangent != -1)
{
printf("stride of is %d\n", stride);
assert(stride >= 60);
glVertexAttribPointer(attrib_bitangent, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)48);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idx);
glBindVertexArray(0);
return vao;
@@ -83,6 +101,55 @@ namespace ObjectPass2Shader
}
}
namespace NormalMapShader
{
GLuint Program;
GLuint attrib_position, attrib_texcoord, attrib_tangent, attrib_bitangent;
GLuint uniform_MVP, uniform_TIMV, uniform_normalMap;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/normalmap.vert").c_str(), file_manager->getAsset("shaders/normalmap.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_tangent = glGetAttribLocation(Program, "Tangent");
attrib_bitangent = glGetAttribLocation(Program, "Bitangent");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_TIMV = glGetUniformLocation(Program, "TransposeInverseModelView");
uniform_normalMap = glGetUniformLocation(Program, "normalMap");
}
void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_normalMap)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_TIMV, 1, GL_FALSE, TransposeInverseModelView.pointer());
glUniform1i(uniform_normalMap, TU_normalMap);
}
}
namespace ColorizeShader
{
GLuint Program;
GLuint attrib_position;
GLuint uniform_MVP, uniform_col;
void init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/colorize.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_col = glGetUniformLocation(Program, "col");
}
void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, float r, float g, float b)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniform3f(uniform_col, r, g, b);
}
}
static
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
{
@@ -156,9 +223,14 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
}
ITexture *tex = mb->getMaterial().getTexture(0);
if (tex)
result.textures = static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
result.textures[0] = static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
else
result.textures = 0;
result.textures[0] = 0;
tex = mb->getMaterial().getTexture(1);
if (tex)
result.textures[1] = static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
else
result.textures[1] = 0;
return result;
}
@@ -178,6 +250,8 @@ STKMesh::STKMesh(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::IScene
return;
ObjectPass1Shader::init();
ObjectPass2Shader::init();
NormalMapShader::init();
ColorizeShader::init();
}
STKMesh::~STKMesh()
@@ -187,7 +261,7 @@ STKMesh::~STKMesh()
}
static
void drawFirstPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
void drawFirstPass(const GLMesh &mesh)
{
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false);
@@ -220,7 +294,48 @@ void drawFirstPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
}
static
void drawSecondPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
void drawNormalPass(const GLMesh &mesh)
{
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false);
glStencilFunc(GL_ALWAYS, 0, ~0);
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
core::matrix4 TransposeInverseModelView = irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
TransposeInverseModelView *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
TransposeInverseModelView.makeInverse();
TransposeInverseModelView = TransposeInverseModelView.getTransposed();
assert(mesh.textures[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mesh.textures[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glUseProgram(NormalMapShader::Program);
NormalMapShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, 0);
glBindVertexArray(mesh.vao_first_pass);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glStencilFunc(GL_ALWAYS, 1, ~0);
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getMainSetup(), false, false);
}
static
void drawSecondPass(const GLMesh &mesh)
{
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
@@ -237,7 +352,7 @@ void drawSecondPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mesh.textures);
glBindTexture(GL_TEXTURE_2D, mesh.textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -261,14 +376,52 @@ void drawSecondPass(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
}
static
void draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
void drawGlow(const GLMesh &mesh, float r, float g, float b)
{
if (!mesh.textures)
glEnable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
glUseProgram(ColorizeShader::Program);
ColorizeShader::setUniforms(ModelViewProjectionMatrix, r, g, b);
glBindVertexArray(mesh.vao_second_pass);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void STKMesh::draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
if (!mesh.textures[0])
return;
if (irr_driver->getPhase() == 0)
drawFirstPass(mesh, type);
else
drawSecondPass(mesh, type);
switch (irr_driver->getPhase())
{
case 0:
if (type == irr_driver->getShader(ES_OBJECTPASS))
drawFirstPass(mesh);
else if (type == irr_driver->getShader(ES_NORMAL_MAP))
drawNormalPass(mesh);
break;
case 1:
drawSecondPass(mesh);
break;
case 2:
{
ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
drawGlow(mesh, cb->getRed(), cb->getGreen(), cb->getBlue());
break;
}
}
video::SMaterial material;
material.MaterialType = irr_driver->getShader(ES_RAIN);
@@ -283,6 +436,8 @@ static bool isObject(video::E_MATERIAL_TYPE type)
{
if (type == irr_driver->getShader(ES_OBJECTPASS))
return true;
if (type == irr_driver->getShader(ES_NORMAL_MAP))
return true;
return false;
}
@@ -290,13 +445,20 @@ static void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
if (mesh.vao_first_pass)
return;
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectPass1Shader::attrib_position, -1, ObjectPass1Shader::attrib_normal,
mesh.Stride);
if (type == irr_driver->getShader(ES_OBJECTPASS))
{
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectPass1Shader::attrib_position, -1, ObjectPass1Shader::attrib_normal, -1, -1, mesh.Stride);
}
else if (type == irr_driver->getShader(ES_NORMAL_MAP))
{
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
NormalMapShader::attrib_position, NormalMapShader::attrib_texcoord, -1, NormalMapShader::attrib_tangent, NormalMapShader::attrib_bitangent, mesh.Stride);
}
mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
ObjectPass2Shader::attrib_position, ObjectPass2Shader::attrib_texcoord, -1,
mesh.Stride);
ObjectPass2Shader::attrib_position, ObjectPass2Shader::attrib_texcoord, -1, -1, -1, mesh.Stride);
mesh.vao_glow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, ColorizeShader::attrib_position, -1, -1, -1, -1, mesh.Stride);
}
void STKMesh::render()
@@ -319,7 +481,7 @@ void STKMesh::render()
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (mb)
{
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType);
bool transparent = (rnd && rnd->isTransparent());

View File

@@ -11,9 +11,10 @@
struct GLMesh {
GLuint vao_first_pass;
GLuint vao_second_pass;
GLuint vao_glow_pass;
GLuint vertex_buffer;
GLuint index_buffer;
GLuint textures;
GLuint textures[2];
GLenum PrimitiveType;
GLenum IndexType;
size_t IndexCount;
@@ -24,6 +25,7 @@ class STKMesh : public irr::scene::CMeshSceneNode
{
protected:
std::vector<GLMesh> GLmeshes;
void draw(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
public:
STKMesh(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position = irr::core::vector3df(0,0,0),

View File

@@ -171,16 +171,16 @@ void FeatureUnlockedCutScene::addTrophy(RaceManager::Difficulty difficulty)
switch (difficulty)
{
case RaceManager::DIFFICULTY_EASY:
msg = _("You completed the easy challenge! This trophy is worth %i points",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]);
msg = _("You completed the easy challenge! Points earned on this level: %i/%i",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
break;
case RaceManager::DIFFICULTY_MEDIUM:
msg = _("You completed the intermediate challenge! This trophy is worth %i points",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]);
msg = _("You completed the intermediate challenge! Points earned on this level: %i/%i",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
break;
case RaceManager::DIFFICULTY_HARD:
msg = _("You completed the difficult challenge! This trophy is worth %i points",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
msg = _("You completed the difficult challenge! Points earned on this level: %i/%i",
CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD], CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]);
break;
default:
assert(false);

View File

@@ -169,7 +169,10 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node
std::string render_pass;
xml_node.get("renderpass", &render_pass);
if(render_pass == "skybox")
bool skeletal_animation = true; // for backwards compatibility, if unspecified assume there is
xml_node.get("skeletal-animation", &skeletal_animation);
if (render_pass == "skybox")
{
m_is_in_skybox = true;
}
@@ -177,8 +180,8 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node
//std::string full_path =
// World::getWorld()->getTrack()->getTrackFile(model_name);
bool animated = (UserConfigParams::m_graphical_effects ||
World::getWorld()->getIdent() == IDENT_CUSTSCENE);
bool animated = skeletal_animation && (UserConfigParams::m_graphical_effects ||
World::getWorld()->getIdent() == IDENT_CUSTSCENE);
if (animated)
@@ -232,7 +235,10 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
void TrackObjectPresentationMesh::init(const XMLNode* xml_node, scene::ISceneNode* parent, bool enabled)
{
bool animated = (UserConfigParams::m_graphical_effects ||
bool skeletal_animation = true; // for backwards compatibility, if unspecified assume there is
xml_node->get("skeletal-animation", &skeletal_animation);
bool animated = skeletal_animation && (UserConfigParams::m_graphical_effects ||
World::getWorld()->getIdent() == IDENT_CUSTSCENE);
m_mesh->grab();