Infrastructure for different rendering paths, includings ones which use ARB_vertex_program instead of NV_vertex_program

ver1_5_1
Chris Laurel 2003-02-19 17:48:25 +00:00
parent 0c68be61c1
commit e7d8fb331e
8 changed files with 700 additions and 185 deletions

View File

@ -34,6 +34,7 @@ OBJS=\
$(INTDIR)\execution.obj \
$(INTDIR)\frame.obj \
$(INTDIR)\galaxy.obj \
$(INTDIR)\glcontext.obj \
$(INTDIR)\glext.obj \
$(INTDIR)\lodspheremesh.obj \
$(INTDIR)\marker.obj \

View File

@ -8,6 +8,7 @@
// of the License, or (at your option) any later version.
#include <algorithm>
#include <celutil/debug.h>
#include "gl.h"
#include "glext.h"
#include "glcontext.h"
@ -15,8 +16,14 @@
using namespace std;
static VertexProcessor* vpNV = NULL;
static VertexProcessor* vpARB = NULL;
GLContext::GLContext() :
renderPath(GLPath_Basic),
vertexPath(VPath_Basic),
vertexProc(NULL),
maxSimultaneousTextures(1)
{
}
@ -75,20 +82,54 @@ void GLContext::init(const vector<string>& ignoreExt)
{
InitExtension(iter->c_str());
}
if (extensionSupported("GL_ARB_vertex_program") &&
glx::glGenProgramsARB)
{
DPRINTF(1, "Renderer: ARB vertex programs supported.\n");
if (vpARB == NULL)
vpARB = vp::initARB();
vertexProc = vpARB;
}
else if (extensionSupported("GL_NV_vertex_program") &&
glx::glGenProgramsNV)
{
DPRINTF(1, "Renderer: nVidia vertex programs supported.\n");
if (vpNV == NULL)
vpNV = vp::initNV();
vertexProc = vpNV;
}
}
bool GLContext::setRenderPath(GLRenderPath path)
{
if (renderPathSupported(path))
{
renderPath = path;
return true;
}
else
if (!renderPathSupported(path))
return false;
switch (path)
{
case GLPath_Basic:
case GLPath_Multitexture:
case GLPath_NvCombiner:
vertexPath = VPath_Basic;
break;
case GLPath_NvCombiner_NvVP:
vertexPath = VPath_NV;
break;
case GLPath_DOT3_ARBVP:
case GLPath_NvCombiner_ARBVP:
case GLPath_ARBFP_ARBVP:
case GLPath_NV30:
vertexPath = VPath_ARB;
break;
default:
return false;
}
renderPath = path;
return true;
}
@ -108,23 +149,30 @@ bool GLContext::renderPathSupported(GLRenderPath path) const
case GLPath_DOT3_ARBVP:
return (extensionSupported("GL_ARB_texture_env_dot3") &&
extensionSupported("GL_ARB_vertex_program"));
extensionSupported("GL_ARB_vertex_program") &&
vertexProc != NULL);
case GLPath_NvCombiner_NvVP:
return (extensionSupported("GL_NV_register_combiners") &&
extensionSupported("GL_NV_vertex_program"));
extensionSupported("GL_NV_vertex_program") &&
vertexProc != NULL);
case GLPath_NvCombiner_ARBVP:
return (extensionSupported("GL_NV_register_combiners") &&
extensionSupported("GL_ARB_vertex_program"));
extensionSupported("GL_ARB_vertex_program") &&
vertexProc != NULL);
case GLPath_ARBFP_ARBVP:
return (extensionSupported("GL_ARB_vertex_program") &&
extensionSupported("GL_ARB_fragment_program"));
extensionSupported("GL_ARB_fragment_program") &&
vertexProc != NULL);
case GLPath_NV30:
return false;
/*
return (extensionSupported("GL_ARB_vertex_program") &&
extensionSupported("GL_NV_fragment_program"));
*/
default:
return false;
@ -142,3 +190,15 @@ bool GLContext::bumpMappingSupported() const
{
return renderPath > GLPath_Multitexture;
}
GLContext::VertexPath GLContext::getVertexPath() const
{
return vertexPath;
}
VertexProcessor* GLContext::getVertexProcessor() const
{
return vertexProc;
}

View File

@ -12,6 +12,7 @@
#include <string>
#include <vector>
#include <celengine/vertexprog.h>
class GLContext
{
@ -31,6 +32,13 @@ class GLContext
GLPath_NV30 = 7,
};
enum VertexPath
{
VPath_Basic = 0,
VPath_NV = 1,
VPath_ARB = 2,
};
void init(const std::vector<std::string>& ignoreExt);
GLRenderPath getRenderPath() const { return renderPath; };
@ -43,8 +51,15 @@ class GLContext
bool hasMultitexture() const { return renderPath >= GLPath_Multitexture; };
bool bumpMappingSupported() const;
VertexPath getVertexPath() const;
VertexProcessor* getVertexProcessor() const;
private:
GLRenderPath renderPath;
VertexPath vertexPath;
VertexProcessor* vertexProc;
int maxSimultaneousTextures;
std::vector<std::string> extensions;
};

View File

@ -105,6 +105,7 @@ static SphericalCoordLabel* coordLabels = NULL;
Renderer::Renderer() :
context(0),
windowWidth(0),
windowHeight(0),
fov(FOV),
@ -120,10 +121,6 @@ Renderer::Renderer() :
saturationMagNight(1.0f),
saturationMag(1.0f),
starVertexBuffer(NULL),
nSimultaneousTextures(1),
useTexEnvCombine(false),
useRegisterCombiners(false),
useCubeMaps(false),
useVertexPrograms(false),
useRescaleNormal(false),
useMinMaxBlending(false),
@ -317,8 +314,10 @@ bool operator<(const RenderListEntry& a, const RenderListEntry& b)
}
bool Renderer::init(int winWidth, int winHeight)
bool Renderer::init(GLContext* _context, int winWidth, int winHeight)
{
context = _context;
// Initialize static meshes and textures common to all instances of Renderer
if (!commonDataInitialized)
{
@ -343,7 +342,7 @@ bool Renderer::init(int winWidth, int winHeight)
// supported, which solves the problem much more elegantly than all
// the mipmap level nonsense.
// shadowTex->setMaxMipMapLevel(3);
useClampToBorder = ExtensionSupported("GL_ARB_texture_border_clamp");
useClampToBorder = context->extensionSupported("GL_ARB_texture_border_clamp");
uint32 texFlags = useClampToBorder ? Texture::BorderClamp : Texture::NoMipMaps;
shadowTex->setBorderColor(Color::White);
shadowTex->bindName(texFlags);
@ -376,16 +375,7 @@ bool Renderer::init(int winWidth, int winHeight)
starTexG = GetTextureManager()->getHandle(TextureInfo("gstar.jpg", 0));
starTexM = GetTextureManager()->getHandle(TextureInfo("mstar.jpg", 0));
// Initialize GL extensions
if (ExtensionSupported("GL_ARB_multitexture"))
InitExtension("GL_ARB_multitexture");
if (ExtensionSupported("GL_NV_register_combiners"))
InitExtension("GL_NV_register_combiners");
if (ExtensionSupported("GL_NV_vertex_program"))
InitExtension("GL_NV_vertex_program");
if (ExtensionSupported("GL_EXT_blend_minmax"))
InitExtension("GL_EXT_blend_minmax");
if (ExtensionSupported("GL_EXT_texture_cube_map"))
if (context->extensionSupported("GL_EXT_texture_cube_map"))
{
// normalizationTex = CreateNormalizationCubeMap(64);
normalizationTex = CreateProceduralCubeMap(64, GL_RGB, IllumMapEval);
@ -433,35 +423,7 @@ bool Renderer::init(int winWidth, int winHeight)
commonDataInitialized = true;
}
// Get GL extension information
if (ExtensionSupported("GL_ARB_multitexture") &&
glx::glActiveTextureARB != NULL)
{
DPRINTF(1, "Renderer: multi-texture supported.\n");
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,
(GLint*) &nSimultaneousTextures);
}
if (ExtensionSupported("GL_EXT_texture_env_combine"))
{
useTexEnvCombine = true;
DPRINTF(1, "Renderer: texture env combine supported.\n");
}
if (ExtensionSupported("GL_NV_register_combiners"))
{
DPRINTF(1, "Renderer: nVidia register combiners supported.\n");
useRegisterCombiners = true;
}
if (ExtensionSupported("GL_NV_vertex_program") && glx::glGenProgramsNV)
{
DPRINTF(1, "Renderer: nVidia vertex programs supported.\n");
useVertexPrograms = vp::init();
}
if (ExtensionSupported("GL_EXT_texture_cube_map"))
{
DPRINTF(1, "Renderer: cube texture maps supported.\n");
useCubeMaps = true;
}
if (ExtensionSupported("GL_EXT_rescale_normal"))
if (context->extensionSupported("GL_EXT_rescale_normal"))
{
// We need this enabled because we use glScale, but only
// with uniform scale factors.
@ -469,7 +431,7 @@ bool Renderer::init(int winWidth, int winHeight)
useRescaleNormal = true;
glEnable(GL_RESCALE_NORMAL_EXT);
}
if (ExtensionSupported("GL_EXT_blend_minmax"))
if (context->extensionSupported("GL_EXT_blend_minmax"))
{
DPRINTF(1, "Renderer: minmax blending supported.\n");
useMinMaxBlending = true;
@ -514,8 +476,6 @@ bool Renderer::init(int winWidth, int winHeight)
}
}
DPRINTF(1, "Simultaneous textures supported: %d\n", nSimultaneousTextures);
glLoadIdentity();
glEnable(GL_CULL_FACE);
@ -667,7 +627,7 @@ void Renderer::setFragmentShaderEnabled(bool enable)
bool Renderer::fragmentShaderSupported() const
{
return useCubeMaps && useRegisterCombiners;
return context->bumpMappingSupported();
}
bool Renderer::getVertexShaderEnabled() const
@ -1924,8 +1884,8 @@ static void renderSphereDefault(const RenderInfo& ri,
}
static void renderSphereFragmentShader(const RenderInfo& ri,
const Frustum& frustum)
static void renderSphere_Combiners(const RenderInfo& ri,
const Frustum& frustum)
{
glDisable(GL_LIGHTING);
@ -1984,8 +1944,8 @@ static void renderSphereFragmentShader(const RenderInfo& ri,
}
static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
const Frustum& frustum)
static void renderSphere_Combiners_NvVP(const RenderInfo& ri,
const Frustum& frustum)
{
Texture* textures[4];
@ -2118,6 +2078,135 @@ static void renderSphereVertexAndFragmentShader(const RenderInfo& ri,
}
static void renderSphere_Combiners_ARBVP(const RenderInfo& ri,
const Frustum& frustum)
{
Texture* textures[4];
if (ri.baseTex == NULL)
{
glDisable(GL_TEXTURE_2D);
}
else
{
glEnable(GL_TEXTURE_2D);
ri.baseTex->bind();
}
// Compute the half angle vector required for specular lighting
Vec3f halfAngle_obj = ri.eyeDir_obj + ri.sunDir_obj;
if (halfAngle_obj.length() != 0.0f)
halfAngle_obj.normalize();
// Set up the fog parameters if the haze density is non-zero
float hazeDensity = ri.hazeColor.alpha();
if (hazeDensity > 0.0f)
{
glEnable(GL_FOG);
float fogColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
fogColor[0] = ri.hazeColor.red();
fogColor[1] = ri.hazeColor.green();
fogColor[2] = ri.hazeColor.blue();
glFogfv(GL_FOG_COLOR, fogColor);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0.0);
glFogf(GL_FOG_END, 1.0f / hazeDensity);
}
glEnable(GL_VERTEX_PROGRAM_ARB);
arbvp::parameter(arbvp::EyePosition, ri.eyePos_obj);
arbvp::parameter(arbvp::SunDirection, ri.sunDir_obj);
arbvp::parameter(arbvp::DiffuseColor, ri.sunColor * ri.color);
arbvp::parameter(arbvp::SpecularExponent, 0.0f, 1.0f, 0.5f, ri.specularPower);
arbvp::parameter(arbvp::SpecularColor, ri.sunColor * ri.specularColor);
arbvp::parameter(arbvp::AmbientColor, ri.ambientColor * ri.color);
arbvp::parameter(arbvp::HazeColor, ri.hazeColor);
if (ri.bumpTex != NULL)
{
if (hazeDensity > 0.0f)
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::diffuseBumpHaze);
else
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::diffuseBump);
SetupCombinersDecalAndBumpMap(*(ri.bumpTex),
ri.ambientColor * ri.color,
ri.sunColor * ri.color);
lodSphere->render(Mesh::Normals | Mesh::Tangents | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
ri.baseTex, ri.bumpTex);
DisableCombiners();
#if 0
// Render a specular pass
if (ri.specularColor != Color::Black)
{
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
vp::parameter(34, ri.sunColor * ri.specularColor);
vp::use(vp::specular);
// Disable ambient and diffuse
vp::parameter(20, Color::Black);
vp::parameter(32, Color::Black);
SetupCombinersGlossMap(ri.glossTex != NULL ? GL_TEXTURE0_ARB : 0);
textures[0] = ri.glossTex != NULL ? ri.glossTex : ri.baseTex;
lodSphere->render(Mesh::Normals | Mesh::TexCoords0,
frustum, ri.lod,
textures, 1);
// re-enable diffuse
vp::parameter(20, ri.sunColor * ri.color);
DisableCombiners();
glDisable(GL_BLEND);
}
#endif
}
else if (ri.specularColor != Color::Black)
{
glEnable(0x8458);
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::specular);
SetupCombinersGlossMapWithFog(ri.glossTex != NULL ? GL_TEXTURE1_ARB : 0);
unsigned int attributes = Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams;
lodSphere->render(attributes, frustum, ri.lod,
ri.baseTex, ri.glossTex);
DisableCombiners();
glDisable(0x8458);
}
else
{
if (hazeDensity > 0.0f)
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::diffuseHaze);
else
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::diffuse);
lodSphere->render(Mesh::Normals | Mesh::TexCoords0 |
Mesh::VertexProgParams, frustum, ri.lod,
ri.baseTex);
}
if (hazeDensity > 0.0f)
glDisable(GL_FOG);
if (ri.nightTex != NULL)
{
ri.nightTex->bind();
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp::nightLights);
setupNightTextureCombine();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
lodSphere->render(Mesh::Normals | Mesh::TexCoords0, frustum, ri.lod,
ri.nightTex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
glDisable(GL_VERTEX_PROGRAM_ARB);
}
static void texGenPlane(GLenum coord, GLenum mode, const Vec4f& plane)
{
float f[4];
@ -2180,17 +2269,20 @@ static void renderShadowedMeshVertexShader(const RenderInfo& ri,
const Frustum& frustum,
float* sPlane, float* tPlane,
Vec3f& lightDir,
bool useShadowMask)
const GLContext& context)
{
vp::enable();
vp::parameter(20, 1, 1, 1, 1); // color = white
vp::parameter(41, sPlane[0], sPlane[1], sPlane[2], sPlane[3]);
vp::parameter(42, tPlane[0], tPlane[1], tPlane[2], tPlane[3]);
if (useShadowMask)
vp::parameter(43, lightDir.x, lightDir.y, lightDir.z, 0.5f);
vp::use(vp::shadowTexture);
VertexProcessor* vproc = context.getVertexProcessor();
assert(vproc != NULL);
vproc->enable();
vproc->parameter(vp::SunDirection, lightDir);
vproc->parameter(vp::TexGen_S, sPlane);
vproc->parameter(vp::TexGen_T, tPlane);
vproc->use(vp::shadowTexture);
lodSphere->render(Mesh::Normals | Mesh::Multipass, frustum, ri.lod, NULL);
vp::disable();
vproc->disable();
}
@ -2199,17 +2291,12 @@ static void renderRings(RingSystem& rings,
float planetRadius,
unsigned int textureResolution,
bool renderShadow,
bool useVertexPrograms)
const GLContext& context)
{
float inner = rings.innerRadius / planetRadius;
float outer = rings.outerRadius / planetRadius;
int nSections = 100;
#if 0
if (useVertexPrograms)
renderShadow = false;
#endif
// Ring Illumination:
// Since a ring system is composed of millions of individual
// particles, it's not at all realistic to model it as a flat
@ -2229,15 +2316,19 @@ static void renderRings(RingSystem& rings,
ringIllumination = illumFraction;
}
if (useVertexPrograms)
GLContext::VertexPath vpath = context.getVertexPath();
VertexProcessor* vproc = context.getVertexProcessor();
if (vproc != NULL)
{
vp::enable();
vp::use(vp::ringIllum);
vp::parameter(16, ri.sunDir_obj);
vp::parameter(20, ri.sunColor * rings.color);
vp::parameter(32, ri.ambientColor * ri.color);
vp::parameter(90, Vec3f(0, 0.5, 1.0));
vproc->enable();
vproc->use(vp::ringIllum);
vproc->parameter(vp::SunDirection, ri.sunDir_obj);
vproc->parameter(vp::DiffuseColor, ri.sunColor * rings.color);
vproc->parameter(vp::AmbientColor, ri.ambientColor * ri.color);
vproc->parameter(vp::Constant0, Vec3f(0, 0.5, 1.0));
}
// If we have multi-texture support, we'll use the second texture unit
// to render the shadow of the planet on the rings. This is a bit of
@ -2270,10 +2361,10 @@ static void renderRings(RingSystem& rings,
sPlane[0] = sAxis.x; sPlane[1] = sAxis.y; sPlane[2] = sAxis.z;
tPlane[0] = tAxis.x; tPlane[1] = tAxis.y; tPlane[2] = tAxis.z;
if (useVertexPrograms)
if (vproc != NULL)
{
vp::parameter(41, sPlane[0], sPlane[1], sPlane[2], sPlane[3]);
vp::parameter(42, tPlane[0], tPlane[1], tPlane[2], tPlane[3]);
vproc->parameter(vp::TexGen_S, sPlane);
vproc->parameter(vp::TexGen_T, tPlane);
}
else
{
@ -2307,10 +2398,7 @@ static void renderRings(RingSystem& rings,
// Perform our own lighting for the rings.
// TODO: Don't forget about light source color (required when we
// paying attention to star color.)
if (useVertexPrograms)
{
}
else
if (vpath == GLContext::VPath_Basic)
{
glDisable(GL_LIGHTING);
Vec3f litColor(rings.color.red(), rings.color.green(), rings.color.blue());
@ -2362,8 +2450,8 @@ static void renderRings(RingSystem& rings,
nSections / 2);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (useVertexPrograms)
vp::disable();
if (vproc != NULL)
vproc->disable();
}
@ -2374,7 +2462,7 @@ renderEclipseShadows(Mesh* mesh,
float planetRadius,
Mat4f& planetMat,
Frustum& viewFrustum,
bool useVertexShader)
const GLContext& context)
{
for (vector<Renderer::EclipseShadow>::iterator iter = eclipseShadows.begin();
iter != eclipseShadows.end(); iter++)
@ -2475,12 +2563,12 @@ renderEclipseShadows(Mesh* mesh,
// standard transformation pipeline isn't guaranteed, we have to
// make sure to use the same transformation engine on subsequent
// rendering passes as we did on the initial one.
if (useVertexShader && mesh == NULL)
if (context.getVertexPath() != GLContext::VPath_Basic && mesh == NULL)
{
renderShadowedMeshVertexShader(ri, viewFrustum,
sPlane, tPlane,
dir,
ri.useTexEnvCombine);
context);
}
else
{
@ -2587,7 +2675,8 @@ renderRingShadowsVS(Mesh* mesh,
float planetRadius,
float oblateness,
Mat4f& planetMat,
Frustum& viewFrustum)
Frustum& viewFrustum,
const GLContext& context)
{
// Compute the transformation to use for generating texture
// coordinates from the object vertices.
@ -2608,18 +2697,15 @@ renderRingShadowsVS(Mesh* mesh,
// If the ambient light level is greater than zero, reduce the
// darkness of the shadows.
if (ri.useTexEnvCombine)
{
float color[4] = { ri.ambientColor.red(), ri.ambientColor.green(),
ri.ambientColor.blue(), 1.0f };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_CONSTANT_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
}
float color[4] = { ri.ambientColor.red(), ri.ambientColor.green(),
ri.ambientColor.blue(), 1.0f };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_CONSTANT_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
// Tweak the texture--set clamp to border and a border color with
// a zero alpha. If a graphics card doesn't support clamp to border,
@ -2637,17 +2723,20 @@ renderRingShadowsVS(Mesh* mesh,
// there is to travel through.
float alpha = (1.0f - abs(ri.sunDir_obj.y)) * 0.5f;
vp::enable();
vp::parameter(16, ri.sunDir_obj);
vp::parameter(20, 1, 1, 1, alpha); // color = white
vp::parameter(43, rings.innerRadius / planetRadius,
1.0f / (ringWidth / planetRadius),
0.0f, 0.5f);
vp::parameter(44, scale, 0, 0, 0);
vp::parameter(45, 1, 1.0f - oblateness, 1, 0);
vp::use(vp::ringShadow);
VertexProcessor* vproc = context.getVertexProcessor();
assert(vproc != NULL);
vproc->enable();
vproc->use(vp::ringShadow);
vproc->parameter(vp::SunDirection, ri.sunDir_obj);
vproc->parameter(vp::DiffuseColor, 1, 1, 1, alpha); // color = white
vproc->parameter(vp::TexGen_S,
rings.innerRadius / planetRadius,
1.0f / (ringWidth / planetRadius),
0.0f, 0.5f);
vproc->parameter(vp::TexGen_T, scale, 0, 0, 0);
lodSphere->render(Mesh::Multipass, viewFrustum, ri.lod, NULL);
vp::disable();
vproc->disable();
// Restore the texture combiners
if (ri.useTexEnvCombine)
@ -2709,7 +2798,7 @@ void Renderer::renderObject(Point3f pos,
if (obj.surface->baseTexture.tex[textureResolution] != InvalidResource)
ri.baseTex = obj.surface->baseTexture.find(textureResolution);
if ((obj.surface->appearanceFlags & Surface::ApplyBumpMap) != 0 &&
(fragmentShaderEnabled && useRegisterCombiners && useCubeMaps) &&
context->bumpMappingSupported() &&
obj.surface->bumpTexture.tex[textureResolution] != InvalidResource)
ri.bumpTex = obj.surface->bumpTexture.find(textureResolution);
if ((obj.surface->appearanceFlags & Surface::ApplyNightMap) != 0 &&
@ -2758,7 +2847,7 @@ void Renderer::renderObject(Point3f pos,
ri.hazeColor = obj.surface->hazeColor;
ri.specularColor = obj.surface->specularColor;
ri.specularPower = obj.surface->specularPower;
ri.useTexEnvCombine = useTexEnvCombine;
ri.useTexEnvCombine = context->getRenderPath() != GLContext::GLPath_Basic;
// See if the surface should be lit
bool lit = (obj.surface->appearanceFlags & Surface::Emissive) == 0;
@ -2832,12 +2921,20 @@ void Renderer::renderObject(Point3f pos,
// you'll miss out on a lot of the eye candy . . .
if (lit)
{
if (fragmentShaderEnabled && vertexShaderEnabled)
renderSphereVertexAndFragmentShader(ri, viewFrustum);
else if (fragmentShaderEnabled && !vertexShaderEnabled)
renderSphereFragmentShader(ri, viewFrustum);
else
switch (context->getRenderPath())
{
case GLContext::GLPath_NvCombiner_ARBVP:
renderSphere_Combiners_ARBVP(ri, viewFrustum);
break;
case GLContext::GLPath_NvCombiner_NvVP:
renderSphere_Combiners_NvVP(ri, viewFrustum);
break;
case GLContext::GLPath_NvCombiner:
renderSphere_Combiners(ri, viewFrustum);
break;
default:
renderSphereDefault(ri, viewFrustum, true);
}
}
else
{
@ -2856,9 +2953,9 @@ void Renderer::renderObject(Point3f pos,
{
renderRings(*obj.rings, ri, radius,
textureResolution,
nSimultaneousTextures > 1 &&
context->getMaxTextures() > 1 &&
(renderFlags & ShowRingShadows) != 0 && lit,
vertexShaderEnabled);
*context);
}
if (obj.atmosphere != NULL)
@ -2917,6 +3014,8 @@ void Renderer::renderObject(Point3f pos,
if (distance - radius < atmosphere->cloudHeight)
glFrontFace(GL_CW);
float texOffset = -pfmod(now * atmosphere->cloudSpeed / (2 * PI), 1.0);
if (atmosphere->cloudSpeed != 0.0f)
{
// Make the clouds appear to rotate above the surface of
@ -2925,8 +3024,7 @@ void Renderer::renderObject(Point3f pos,
// texture matrix doesn't require us to compute a second
// set of model space rendering parameters.
glMatrixMode(GL_TEXTURE);
glTranslatef(-pfmod(now * atmosphere->cloudSpeed / (2*PI),
1.0), 0, 0);
glTranslatef(texOffset, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
}
@ -2939,24 +3037,24 @@ void Renderer::renderObject(Point3f pos,
if (lit)
{
if (vertexShaderEnabled)
VertexProcessor* vproc = context->getVertexProcessor();
if (vproc != NULL)
{
vp::enable();
vp::use(vp::diffuseTexOffset);
vp::parameter(20, ri.sunColor * ri.color);
vp::parameter(32, ri.ambientColor * ri.color);
vp::parameter(41,
(float) -pfmod(now * atmosphere->cloudSpeed / (2*PI), 1.0),
0.0f, 0.0f, 0.0f);
vproc->enable();
vproc->use(vp::diffuseTexOffset);
vproc->parameter(vp::DiffuseColor, ri.sunColor * ri.color);
vproc->parameter(vp::AmbientColor, ri.ambientColor * ri.color);
vproc->parameter(vp::TextureTranslation,
texOffset, 0.0f, 0.0f, 0.0f);
}
lodSphere->render(Mesh::Normals | Mesh::TexCoords0,
viewFrustum,
ri.lod,
cloudTex);
if (vertexShaderEnabled)
{
vp::disable();
}
if (vproc != NULL)
vproc->disable();
}
else
{
@ -2986,7 +3084,7 @@ void Renderer::renderObject(Point3f pos,
*obj.eclipseShadows,
ri,
radius, planetMat, viewFrustum,
vertexShaderEnabled);
*context);
}
if (obj.rings != NULL &&
@ -3001,14 +3099,16 @@ void Renderer::renderObject(Point3f pos,
ringsTex->bind();
if (useClampToBorder && vertexShaderEnabled)
if (useClampToBorder &&
context->getVertexPath() != GLContext::VPath_Basic)
{
renderRingShadowsVS(mesh,
*obj.rings,
sunDir,
ri,
radius, obj.oblateness,
planetMat, viewFrustum);
planetMat, viewFrustum,
*context);
}
else if (useClampToBorder)
{
@ -3029,9 +3129,9 @@ void Renderer::renderObject(Point3f pos,
{
renderRings(*obj.rings, ri, radius,
textureResolution,
nSimultaneousTextures > 1 &&
(renderFlags & ShowRingShadows) != 0 && lit,
vertexShaderEnabled);
(context->hasMultitexture() &&
(renderFlags & ShowRingShadows) != 0 && lit),
*context);
}
glPopMatrix();
@ -4479,7 +4579,7 @@ void Renderer::loadTextures(Body* body)
if (surface.baseTexture.tex[textureResolution] != InvalidResource)
surface.baseTexture.find(textureResolution);
if ((surface.appearanceFlags & Surface::ApplyBumpMap) != 0 &&
(fragmentShaderEnabled && useRegisterCombiners && useCubeMaps) &&
context->bumpMappingSupported() &&
surface.bumpTexture.tex[textureResolution] != InvalidResource)
surface.bumpTexture.find(textureResolution);
if ((surface.appearanceFlags & Surface::ApplyNightMap) != 0 &&

View File

@ -15,6 +15,7 @@
#include <celengine/observer.h>
#include <celengine/universe.h>
#include <celengine/selection.h>
#include <celengine/glcontext.h>
#include <celtxf/texturefont.h>
@ -39,7 +40,7 @@ class Renderer
Renderer();
~Renderer();
bool init(int, int);
bool init(GLContext*, int, int);
void shutdown() {};
void resize(int, int);
@ -273,6 +274,8 @@ class Renderer
const Point3d&, const Point3d&);
private:
GLContext* context;
int windowWidth;
int windowHeight;
float fov;
@ -308,10 +311,6 @@ class Renderer
double modelMatrix[16];
double projMatrix[16];
int nSimultaneousTextures;
bool useTexEnvCombine;
bool useRegisterCombiners;
bool useCubeMaps;
bool useCompressedTextures;
bool useVertexPrograms;
bool useRescaleNormal;

View File

@ -31,6 +31,34 @@ unsigned int vp::cometTail = 0;
unsigned int vp::nightLights = 0;
class VertexProcessorNV : public VertexProcessor
{
public:
VertexProcessorNV();
virtual ~VertexProcessorNV();
virtual void enable();
virtual void disable();
virtual void use(unsigned int);
virtual void parameter(vp::Parameter, float, float, float, float);
virtual void parameter(vp::Parameter, const float*);
};
class VertexProcessorARB : public VertexProcessor
{
public:
VertexProcessorARB();
virtual ~VertexProcessorARB();
virtual void enable();
virtual void disable();
virtual void use(unsigned int);
virtual void parameter(vp::Parameter, float, float, float, float);
virtual void parameter(vp::Parameter, const float*);
};
static string* ReadTextFromFile(const string& filename)
{
ifstream textFile(filename.c_str(), ios::in);
@ -47,14 +75,14 @@ static string* ReadTextFromFile(const string& filename)
}
static bool LoadVertexProgram(const string& filename, unsigned int& id)
static bool LoadNvVertexProgram(const string& filename, unsigned int& id)
{
cout << "Loading vertex program: " << filename << '\n';
cout << "Loading NV vertex program: " << filename << '\n';
string* source = ReadTextFromFile(filename);
if (source == NULL)
{
cout << "Error loading vertex program: " << filename << '\n';
cout << "Error loading NV vertex program: " << filename << '\n';
return false;
}
@ -80,39 +108,129 @@ static bool LoadVertexProgram(const string& filename, unsigned int& id)
}
bool vp::init()
static int findLineNumber(const string& s, int index)
{
cout << "Initializing vertex programs . . .\n";
if (!LoadVertexProgram("shaders/diffuse.vp", diffuse))
if (index >= s.length())
return -1;
int lineno = 1;
for (int i = 0; i < index; i++)
{
if (s[i] == '\n')
lineno++;
}
return lineno;
}
static bool LoadARBVertexProgram(const string& filename, unsigned int& id)
{
cout << "Loading ARB vertex program: " << filename << '\n';
string* source = ReadTextFromFile(filename);
if (source == NULL)
{
cout << "Error loading ARB vertex program: " << filename << '\n';
return false;
if (!LoadVertexProgram("shaders/specular.vp", specular))
}
glx::glGenProgramsARB(1, (GLuint*) &id);
if (glGetError() != GL_NO_ERROR)
{
delete source;
return false;
if (!LoadVertexProgram("shaders/haze.vp", diffuseHaze))
return false;
if (!LoadVertexProgram("shaders/bumpdiffuse.vp", diffuseBump))
return false;
if (!LoadVertexProgram("shaders/bumphaze.vp", diffuseBumpHaze))
return false;
if (!LoadVertexProgram("shaders/shadowtex.vp", shadowTexture))
return false;
if (!LoadVertexProgram("shaders/diffuse_texoff.vp", diffuseTexOffset))
return false;
if (!LoadVertexProgram("shaders/rings.vp", ringIllum))
return false;
if (!LoadVertexProgram("shaders/ringshadow.vp", ringShadow))
return false;
if (!LoadVertexProgram("shaders/night.vp", nightLights))
return false;
// if (!LoadVertexProgram("shaders/comet.vp", cometTail))
}
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, id);
glx::glProgramStringARB(GL_VERTEX_PROGRAM_ARB,
GL_PROGRAM_FORMAT_ASCII_ARB,
source->length(),
reinterpret_cast<const GLubyte*>(source->c_str()));
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
GLint errPos = 0;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
const char* errMsg = (const char*) glGetString(GL_PROGRAM_ERROR_STRING_ARB);
if (errMsg == NULL)
errMsg = "Unknown error";
cout << "Error in vertex program " << filename <<
", line " << findLineNumber(*source, errPos) << ": " << errMsg << '\n';
}
delete source;
return err == GL_NO_ERROR;
}
VertexProcessor* vp::initNV()
{
cout << "Initializing NV vertex programs . . .\n";
if (!LoadNvVertexProgram("shaders/diffuse.vp", diffuse))
return NULL;
if (!LoadNvVertexProgram("shaders/specular.vp", specular))
return NULL;
if (!LoadNvVertexProgram("shaders/haze.vp", diffuseHaze))
return NULL;
if (!LoadNvVertexProgram("shaders/bumpdiffuse.vp", diffuseBump))
return NULL;
if (!LoadNvVertexProgram("shaders/bumphaze.vp", diffuseBumpHaze))
return NULL;
if (!LoadNvVertexProgram("shaders/shadowtex.vp", shadowTexture))
return NULL;
if (!LoadNvVertexProgram("shaders/diffuse_texoff.vp", diffuseTexOffset))
return NULL;
if (!LoadNvVertexProgram("shaders/rings.vp", ringIllum))
return NULL;
if (!LoadNvVertexProgram("shaders/ringshadow.vp", ringShadow))
return NULL;
if (!LoadNvVertexProgram("shaders/night.vp", nightLights))
return NULL;
// if (!LoadNvVertexProgram("shaders/comet.vp", cometTail))
// return false;
everything = 0;
cout << "All NV vertex programs loaded successfully.\n";
glx::glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,
0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
glx::glTrackMatrixNV(GL_VERTEX_PROGRAM_NV,
4, GL_MODELVIEW_PROJECTION_NV, GL_INVERSE_TRANSPOSE_NV);
return true;
return new VertexProcessorNV();
}
VertexProcessor* vp::initARB()
{
cout << "Initializing ARB vertex programs . . .\n";
if (!LoadARBVertexProgram("shaders/diffuse_arb.vp", diffuse))
return NULL;
if (!LoadARBVertexProgram("shaders/specular_arb.vp", specular))
return NULL;
if (!LoadARBVertexProgram("shaders/haze_arb.vp", diffuseHaze))
return NULL;
if (!LoadARBVertexProgram("shaders/bumpdiffuse_arb.vp", diffuseBump))
return NULL;
if (!LoadARBVertexProgram("shaders/bumphaze_arb.vp", diffuseBumpHaze))
return NULL;
if (!LoadARBVertexProgram("shaders/shadowtex_arb.vp", shadowTexture))
return NULL;
if (!LoadARBVertexProgram("shaders/diffuse_texoff_arb.vp", diffuseTexOffset))
return NULL;
if (!LoadARBVertexProgram("shaders/rings_arb.vp", ringIllum))
return NULL;
if (!LoadARBVertexProgram("shaders/ringshadow_arb.vp", ringShadow))
return NULL;
if (!LoadARBVertexProgram("shaders/night_arb.vp", nightLights))
return NULL;
cout << "All ARB vertex programs loaded successfully.\n";
return new VertexProcessorARB();
}
@ -139,21 +257,166 @@ void vp::parameter(unsigned int param, const Vec3f& v)
glx::glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, param, v.x, v.y, v.z, 0.0f);
}
void vp::parameter(unsigned int param, const Point3f& p)
{
glx::glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, param, p.x, p.y, p.z, 0.0f);
}
void vp::parameter(unsigned int param, const Color& c)
{
glx::glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, param,
c.red(), c.green(), c.blue(), c.alpha());
}
void vp::parameter(unsigned int param, float x, float y, float z, float w)
{
glx::glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, param, x, y, z, w);
}
void arbvp::parameter(unsigned int param, const Vec3f& v)
{
glx::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, param,
v.x, v.y, v.z, 0.0f);
}
void arbvp::parameter(unsigned int param, const Point3f& p)
{
glx::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, param,
p.x, p.y, p.z, 0.0f);
}
void arbvp::parameter(unsigned int param, const Color& c)
{
glx::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, param,
c.red(), c.green(), c.blue(), c.alpha());
}
void arbvp::parameter(unsigned int param, float x, float y, float z, float w)
{
glx::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, param, x, y, z, w);
}
void arbvp::parameter(unsigned int param, const float* fv)
{
glx::glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, param, fv);
}
VertexProcessor::VertexProcessor()
{
}
VertexProcessor::~VertexProcessor()
{
}
void VertexProcessor::parameter(vp::Parameter param, const Vec3f& v)
{
parameter(param, v.x, v.y, v.z, 0.0f);
}
void VertexProcessor::parameter(vp::Parameter param, const Point3f& p)
{
parameter(param, p.x, p.y, p.z, 0.0f);
}
void VertexProcessor::parameter(vp::Parameter param, const Color& c)
{
parameter(param, c.red(), c.green(), c.blue(), c.alpha());
}
// VertexProcessorNV implementation
static unsigned int parameterMappings[] =
{
16, // SunDirection,
15, // EyePosition,
20, // DiffuseColor
34, // SpecularColor
40, // SpecularExponent
32, // AmbientColor
33, // HazeColor
41, // TextureTranslation
90, // Constant0 - relevant for NV_vertex_program only
0, // Unused
41, // TexGen_S,
42, // TexGen_Y
};
VertexProcessorNV::VertexProcessorNV()
{
}
VertexProcessorNV::~VertexProcessorNV()
{
}
void VertexProcessorNV::enable()
{
glEnable(GL_VERTEX_PROGRAM_NV);
}
void VertexProcessorNV::disable()
{
glDisable(GL_VERTEX_PROGRAM_NV);
}
void VertexProcessorNV::use(unsigned int prog)
{
glx::glBindProgramNV(GL_VERTEX_PROGRAM_NV, prog);
}
void VertexProcessorNV::parameter(vp::Parameter param,
float x, float y, float z, float w)
{
glx::glProgramParameter4fNV(GL_VERTEX_PROGRAM_NV,
parameterMappings[param], x, y, z, w);
}
void VertexProcessorNV::parameter(vp::Parameter param, const float* fv)
{
glx::glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV,
parameterMappings[param], fv);
}
// VertexProcessorARB implementation
VertexProcessorARB::VertexProcessorARB()
{
}
VertexProcessorARB::~VertexProcessorARB()
{
}
void VertexProcessorARB::enable()
{
glEnable(GL_VERTEX_PROGRAM_ARB);
}
void VertexProcessorARB::disable()
{
glDisable(GL_VERTEX_PROGRAM_ARB);
}
void VertexProcessorARB::use(unsigned int prog)
{
glx::glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog);
}
void VertexProcessorARB::parameter(vp::Parameter param,
float x, float y, float z, float w)
{
glx::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, param, x, y, z, w);
}
void VertexProcessorARB::parameter(vp::Parameter param, const float* fv)
{
glx::glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, param, fv);
}

View File

@ -13,9 +13,13 @@
#include <celmath/vecmath.h>
#include <celutil/color.h>
class VertexProcessor;
namespace vp
{
bool init();
VertexProcessor* initNV();
VertexProcessor* initARB();
void enable();
void disable();
void use(unsigned int);
@ -25,6 +29,20 @@ namespace vp
void parameter(unsigned int, const Color&);
void parameter(unsigned int, float, float, float, float);
enum Parameter {
SunDirection = 0,
EyePosition = 1,
DiffuseColor = 2,
SpecularColor = 3,
SpecularExponent = 4,
AmbientColor = 5,
HazeColor = 6,
TextureTranslation = 7,
Constant0 = 8,
TexGen_S = 10,
TexGen_T = 11,
};
extern unsigned int specular;
extern unsigned int diffuse;
extern unsigned int diffuseHaze;
@ -39,4 +57,49 @@ namespace vp
extern unsigned int nightLights;
};
namespace arbvp
{
enum EnvParam {
SunDirection = 0,
EyePosition = 1,
DiffuseColor = 2,
SpecularColor = 3,
SpecularExponent = 4,
AmbientColor = 5,
HazeColor = 6,
TextureTranslation = 7,
Constant0 = 8,
TexGen_S = 10,
TexGen_T = 11,
};
void parameter(unsigned int, const Vec3f&);
void parameter(unsigned int, const Point3f&);
void parameter(unsigned int, const Color&);
void parameter(unsigned int, float, float, float, float);
void parameter(unsigned int, const float*);
};
class VertexProcessor
{
public:
VertexProcessor();
virtual ~VertexProcessor();
virtual void enable() = 0;
virtual void disable() = 0;
virtual void use(unsigned int) = 0;
virtual void parameter(vp::Parameter, const Vec3f&);
virtual void parameter(vp::Parameter, const Point3f&);
virtual void parameter(vp::Parameter, const Color&);
virtual void parameter(vp::Parameter, float, float, float, float) = 0;
virtual void parameter(vp::Parameter, const float*) = 0;
private:
int dummy;
};
#endif // _VERTEXPROG_H_

View File

@ -2427,8 +2427,22 @@ bool CelestiaCore::initRenderer()
Renderer::ShowAtmospheres |
Renderer::ShowAutoMag);
GLContext* context = new GLContext();
assert(context != NULL);
if (context == NULL)
return false;
context->init(config->ignoreGLExtensions);
// Choose the render path, starting with the least desirable
context->setRenderPath(GLContext::GLPath_Basic);
context->setRenderPath(GLContext::GLPath_Multitexture);
context->setRenderPath(GLContext::GLPath_DOT3_ARBVP);
context->setRenderPath(GLContext::GLPath_NvCombiner_NvVP);
context->setRenderPath(GLContext::GLPath_NvCombiner_ARBVP);
cout << "render path: " << context->getRenderPath() << '\n';
// Prepare the scene for rendering.
if (!renderer->init((int) width, (int) height))
if (!renderer->init(context, (int) width, (int) height))
{
fatalError("Failed to initialize renderer");
return false;