Refactoring of texture code

- refactored texture structs & functions
- added note about OpenGL extensions
- removed device.cpp as unnecessary
- minor changes in CEngine
dev-ui
Piotr Dziwinski 2012-07-25 00:27:01 +02:00
parent 9d59204531
commit 42963b341f
10 changed files with 282 additions and 298 deletions

View File

@ -170,14 +170,6 @@ bool CApplication::Create()
// Create the 3D engine
m_engine = new Gfx::CEngine(m_iMan, this);
// Initialize the app's custom scene stuff, but before initializing the graphics device
if (! m_engine->BeforeCreateInit())
{
SystemDialog(SDT_ERROR, "COLOBOT - Error", std::string("Error in CEngine::BeforeCreateInit() :\n") +
std::string(m_engine->GetError()) );
m_exitCode = 1;
return false;
}
/* // Create the sound instance.
m_sound = new CSound(m_iMan);

View File

@ -1,33 +0,0 @@
// * This file is part of the COLOBOT source code
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
// device.cpp
#include "graphics/common/device.h"
void Gfx::DeviceConfig::LoadDefault()
{
width = 800;
height = 600;
bpp = 32;
fullScreen = false;
resizeable = false;
doubleBuf = true;
noFrame = false;
}

View File

@ -62,7 +62,16 @@ struct DeviceConfig
DeviceConfig() { LoadDefault(); }
//! Loads the default values
void LoadDefault();
inline void LoadDefault()
{
width = 800;
height = 600;
bpp = 32;
fullScreen = false;
resizeable = false;
doubleBuf = true;
noFrame = false;
}
};
@ -326,10 +335,10 @@ public:
//! Returns the current enable state of given texture stage
virtual bool GetTextureEnabled(int index) = 0;
//! Sets the current params of texture with given index
virtual void SetTextureParams(int index, const Gfx::TextureParams &params) = 0;
//! Returns the current params of texture with given index
virtual Gfx::TextureParams GetTextureParams(int index) = 0;
//! Sets the params for texture stage with given index
virtual void SetTextureStageParams(int index, const Gfx::TextureStageParams &params) = 0;
//! Returns the current params of texture stage with given index
virtual Gfx::TextureStageParams GetTextureStageParams(int index) = 0;
//! Sets the texture factor to the given color value
virtual void SetTextureFactor(const Gfx::Color &color) = 0;

View File

@ -52,13 +52,13 @@ Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
m_iMan->AddInstance(CLASS_ENGINE, this);
m_app = app;
/*m_light = new Gfx::CLight(m_iMan, this);
m_text = new Gfx::CText(m_iMan, this);
m_particle = new Gfx::CParticle(m_iMan, this);
m_water = new Gfx::CWater(m_iMan, this);
m_cloud = new Gfx::CCloud(m_iMan, this);
m_lightning = new Gfx::CLightning(m_iMan, this);
m_planet = new Gfx::CPlanet(m_iMan, this);*/
m_light = NULL;
m_text = NULL;
m_particle = NULL;
m_water = NULL;
m_cloud = NULL;
m_lightning = NULL;
m_planet = NULL;
m_sound = NULL;
m_terrain = NULL;
@ -185,6 +185,43 @@ Gfx::CEngine::~CEngine()
m_app = NULL;
m_device = NULL;
m_sound = NULL;
m_terrain = NULL;
}
bool Gfx::CEngine::GetWasInit()
{
return m_wasInit;
}
std::string Gfx::CEngine::GetError()
{
return m_error;
}
bool Gfx::CEngine::Create()
{
m_wasInit = true;
/*m_light = new Gfx::CLight(m_iMan, this);
m_text = new Gfx::CText(m_iMan, this);
m_particle = new Gfx::CParticle(m_iMan, this);
m_water = new Gfx::CWater(m_iMan, this);
m_cloud = new Gfx::CCloud(m_iMan, this);
m_lightning = new Gfx::CLightning(m_iMan, this);
m_planet = new Gfx::CPlanet(m_iMan, this);*/
m_matWorldInterface.LoadIdentity();
m_matViewInterface.LoadIdentity();
Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
return true;
}
void Gfx::CEngine::Destroy()
{
// TODO
/*delete m_light;
m_light = NULL;
@ -206,41 +243,6 @@ Gfx::CEngine::~CEngine()
delete m_planet;
m_planet = NULL;*/
m_sound = NULL;
m_terrain = NULL;
}
bool Gfx::CEngine::GetWasInit()
{
return m_wasInit;
}
std::string Gfx::CEngine::GetError()
{
return m_error;
}
bool Gfx::CEngine::BeforeCreateInit()
{
// TODO
return true;
}
bool Gfx::CEngine::Create()
{
m_wasInit = true;
m_matWorldInterface.LoadIdentity();
m_matViewInterface.LoadIdentity();
Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
return true;
}
void Gfx::CEngine::Destroy()
{
// TODO
m_wasInit = false;
}
@ -265,7 +267,7 @@ bool Gfx::CEngine::AfterDeviceSetInit()
params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST;
params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
params.mipmap = false;
CreateTexture("mouse.png", params);
m_miceTexture = CreateTexture("mouse.png", params);
return true;
}
@ -360,12 +362,12 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color)
m_device->SetTextureEnabled(0, true);
m_device->SetTextureFactor(color);
Gfx::TextureParams params;
Gfx::TextureStageParams params;
params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE;
params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR;
params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
m_device->SetTextureParams(0, params);
m_device->SetTextureStageParams(0, params);
}
else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture?
{
@ -379,12 +381,12 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color)
m_device->SetTextureEnabled(0, true);
m_device->SetTextureFactor(color.Inverse());
Gfx::TextureParams params;
Gfx::TextureStageParams params;
params.colorOperation = Gfx::TEX_MIX_OPER_ADD;
params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE;
params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR;
params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
m_device->SetTextureParams(0, params);
m_device->SetTextureStageParams(0, params);
}
else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color?
{
@ -398,7 +400,7 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color)
m_device->SetTextureFactor(color);
m_device->SetTextureEnabled(0, true);
m_device->SetTextureParams(0, Gfx::TextureParams());
m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
}
else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color?
{
@ -412,7 +414,7 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color)
m_device->SetTextureFactor(color.Inverse());
m_device->SetTextureEnabled(0, true);
m_device->SetTextureParams(0, Gfx::TextureParams());
m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
}
else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent?
{
@ -454,7 +456,7 @@ void Gfx::CEngine::SetState(int state, Gfx::Color color)
m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
m_device->SetTextureEnabled(0, true);
m_device->SetTextureParams(0, Gfx::TextureParams());
m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
/*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
@ -620,8 +622,8 @@ void Gfx::CEngine::DrawMouse()
material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f);
material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f);
SetMaterial(material);
SetTexture("mouse.png");
m_device->SetMaterial(material);
m_device->SetTexture(0, m_miceTexture);
int index = static_cast<int>(m_mouseType);

View File

@ -516,7 +516,6 @@ public:
bool GetWasInit();
std::string GetError();
bool BeforeCreateInit();
bool Create();
void Destroy();
@ -970,6 +969,7 @@ protected:
std::map<Gfx::Texture, std::string> m_revTexNameMap;
Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT];
Gfx::Texture m_miceTexture;
Math::Point m_mouseSize;
Gfx::EngineMouseType m_mouseType;
Math::Point m_mousePos;

View File

@ -25,15 +25,21 @@ namespace Gfx {
\brief Format of image data */
enum TexImgFormat
{
//! Try to determine automatically (may not work)
TEX_IMG_AUTO,
//! RGB triplet, 3 bytes
TEX_IMG_RGB,
//! BGR triplet, 3 bytes
TEX_IMG_BGR,
//! RGBA triplet, 4 bytes
TEX_IMG_RGBA,
//! BGRA triplet, 4 bytes
TEX_IMG_BGRA
};
/**
\enum TexMinFilter
\brief Minification texture filter
\brief Texture minification filter
Corresponds to OpenGL modes but should translate to DirectX too. */
enum TexMinFilter
@ -48,7 +54,7 @@ enum TexMinFilter
/**
\enum TexMagFilter
\brief Magnification texture filter */
\brief Texture magnification filter */
enum TexMagFilter
{
TEX_MAG_FILTER_NEAREST,
@ -66,30 +72,42 @@ enum TexWrapMode
/**
\enum TexMixOperation
\brief Multitexture mixing operation
*/
\brief Multitexture mixing operation */
enum TexMixOperation
{
//! Default operation on default params (modulate on computed & texture)
TEX_MIX_OPER_DEFAULT,
//! = Arg1
TEX_MIX_OPER_REPLACE,
//! = Arg1 * Arg2
TEX_MIX_OPER_MODULATE,
TEX_MIX_OPER_ADD
//! = Arg1 + Arg2
TEX_MIX_OPER_ADD,
//! = Arg1 - Arg2
TEX_MIX_OPER_SUBTRACT
};
/**
\enum TexMixArgument
\brief Multitexture mixing argument
*/
\brief Multitexture mixing argument */
enum TexMixArgument
{
TEX_MIX_ARG_CURRENT,
//! Color from current texture
TEX_MIX_ARG_TEXTURE,
TEX_MIX_ARG_DIFFUSE,
//! Color computed by previous texture unit (current in DirectX; previous in OpenGL)
TEX_MIX_ARG_COMPUTED_COLOR,
//! (Source) color of textured fragment (diffuse in DirectX; primary color in OpenGL)
TEX_MIX_ARG_SRC_COLOR,
//! Constant color (texture factor in DirectX; texture env color in OpenGL)
TEX_MIX_ARG_FACTOR
};
/**
\struct TextureCreateParams
\brief Parameters for texture creation
*/
These params define how particular texture is created and later displayed.
They must be specified at texture creation time and cannot be changed later. */
struct TextureCreateParams
{
//! Whether to generate mipmaps
@ -100,10 +118,6 @@ struct TextureCreateParams
Gfx::TexMinFilter minFilter;
//! Magnification filter
Gfx::TexMagFilter magFilter;
//! Wrap S coord mode
Gfx::TexWrapMode wrapS;
//! Wrap T coord mode
Gfx::TexWrapMode wrapT;
//! Constructor; calls LoadDefault()
TextureCreateParams()
@ -117,17 +131,16 @@ struct TextureCreateParams
minFilter = Gfx::TEX_MIN_FILTER_NEAREST;
magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
wrapS = Gfx::TEX_WRAP_REPEAT;
wrapT = Gfx::TEX_WRAP_REPEAT;
}
};
/**
\struct TextureParams
\brief Parameters for texture creation
*/
struct TextureParams
\struct TextureStageParams
\brief Parameters for a texture unit
These params define the behavior of texturing units (stages).
They can be changed freely and are feature of graphics engine, not any particular texture. */
struct TextureStageParams
{
//! Mixing operation done on color values
Gfx::TexMixOperation colorOperation;
@ -141,30 +154,41 @@ struct TextureParams
Gfx::TexMixArgument alphaArg1;
//! 2nd argument of alpha operations
Gfx::TexMixArgument alphaArg2;
//! Wrap mode for 1st tex coord
Gfx::TexWrapMode wrapS;
//! Wrap mode for 2nd tex coord
Gfx::TexWrapMode wrapT;
//! Constructor; calls LoadDefault()
TextureParams()
TextureStageParams()
{ LoadDefault(); }
//! Loads the default values
inline void LoadDefault()
{
colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
colorArg1 = Gfx::TEX_MIX_ARG_CURRENT;
colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
colorArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
alphaArg1 = Gfx::TEX_MIX_ARG_CURRENT;
alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
alphaArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
alphaArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
wrapS = wrapT = Gfx::TEX_WRAP_REPEAT;
}
};
/** \struct Texture*/
/**
\struct Texture
\brief Info about a texture
Identifies (through id) a texture created in graphics engine.
Also contains some additional data. */
struct Texture
{
//! Whether the texture was loaded
//! Whether the texture (ID) is valid
bool valid;
//! Id of the texture in graphics engine
//! ID of the texture in graphics engine
unsigned int id;
//! Width of texture
int width;

View File

@ -20,6 +20,7 @@
#include "graphics/opengl/gldevice.h"
#include "math/geometry.h"
// Should define prototypes of used extensions as OpenGL functions
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
@ -71,24 +72,9 @@ std::string Gfx::CGLDevice::GetError()
bool Gfx::CGLDevice::Create()
{
/* First check for extensions
These should be available in standard OpenGL 1.3
But every distribution is different
So we're loading them dynamically through SDL_GL_GetProcAddress() */
std::string extensions = std::string( (char*) glGetString(GL_EXTENSIONS));
if (extensions.find("GL_ARB_multitexture") == std::string::npos)
{
m_error = "Required extension GL_ARB_multitexture not supported";
return false;
}
if (extensions.find("GL_EXT_texture_env_combine") == std::string::npos)
{
m_error = "Required extension GL_EXT_texture_env_combine not supported";
return false;
}
/* NOTE: extension testing is not done here as the assumed version of OpenGL to be used (1.4+)
must already have the required extensions. The used extensions are listed here for reference:
GL_ARB_multitexture, GL_EXT_texture_env_combine, GL_EXT_secondary_color */
m_wasInit = true;
@ -112,11 +98,11 @@ bool Gfx::CGLDevice::Create()
m_lightsEnabled = std::vector<bool> (GL_MAX_LIGHTS, false);
int maxTextures = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextures);
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures);
m_textures = std::vector<Gfx::Texture> (maxTextures, Gfx::Texture());
m_currentTextures = std::vector<Gfx::Texture> (maxTextures, Gfx::Texture());
m_texturesEnabled = std::vector<bool> (maxTextures, false);
m_texturesParams = std::vector<Gfx::TextureParams>(maxTextures, Gfx::TextureParams());
m_textureStageParams = std::vector<Gfx::TextureStageParams>(maxTextures, Gfx::TextureStageParams());
return true;
}
@ -130,9 +116,9 @@ void Gfx::CGLDevice::Destroy()
m_lights.clear();
m_lightsEnabled.clear();
m_textures.clear();
m_currentTextures.clear();
m_texturesEnabled.clear();
m_texturesParams.clear();
m_textureStageParams.clear();
m_wasInit = false;
}
@ -324,7 +310,7 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCrea
result.height = data->surface->h;
// Use & enable 1st texture stage
glActiveTextureARB(GL_TEXTURE0_ARB);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -352,19 +338,6 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCrea
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magF);
if (params.wrapS == Gfx::TEX_WRAP_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
else if (params.wrapS == Gfx::TEX_WRAP_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
else assert(false);
if (params.wrapT == Gfx::TEX_WRAP_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
else if (params.wrapT == Gfx::TEX_WRAP_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else assert(false);
if (params.mipmap)
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
else
@ -399,8 +372,8 @@ Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCrea
// Restore the previous state of 1st stage
if (m_textures[0].valid)
glBindTexture(GL_TEXTURE_2D, m_textures[0].id);
if (m_currentTextures[0].valid)
glBindTexture(GL_TEXTURE_2D, m_currentTextures[0].id);
else
glBindTexture(GL_TEXTURE_2D, 0);
@ -417,9 +390,9 @@ void Gfx::CGLDevice::DestroyTexture(const Gfx::Texture &texture)
m_allTextures.erase(it);
// Unbind the texture if in use anywhere
for (int index = 0; index < (int)m_textures.size(); ++index)
for (int index = 0; index < (int)m_currentTextures.size(); ++index)
{
if (m_textures[index] == texture)
if (m_currentTextures[index] == texture)
SetTexture(index, Gfx::Texture()); // set to invalid texture
}
@ -436,7 +409,7 @@ void Gfx::CGLDevice::DestroyAllTextures()
int Gfx::CGLDevice::GetMaxTextureCount()
{
return m_textures.size();
return m_currentTextures.size();
}
/**
@ -446,13 +419,13 @@ int Gfx::CGLDevice::GetMaxTextureCount()
void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
// Enable the given texture stage
glActiveTextureARB(GL_TEXTURE0_ARB + index);
glActiveTexture(GL_TEXTURE0 + index);
glEnable(GL_TEXTURE_2D);
m_textures[index] = texture; // remember the change
m_currentTextures[index] = texture; // remember the change
if (! texture.valid)
{
@ -460,8 +433,8 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
}
else
{
glBindTexture(GL_TEXTURE_2D, texture.id); // bind the texture
SetTextureParams(index, m_texturesParams[index]); // texture params need to be re-set for the new texture
glBindTexture(GL_TEXTURE_2D, texture.id); // bind the texture
SetTextureStageParams(index, m_textureStageParams[index]); // texture stage params need to be re-set for the new texture
}
// Disable the stage if it is set so
@ -474,19 +447,19 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
Gfx::Texture Gfx::CGLDevice::GetTexture(int index)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
return m_textures[index];
return m_currentTextures[index];
}
void Gfx::CGLDevice::SetTextureEnabled(int index, bool enabled)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
m_texturesEnabled[index] = enabled;
glActiveTextureARB(GL_TEXTURE0_ARB + index);
glActiveTexture(GL_TEXTURE0 + index);
if (enabled)
glEnable(GL_TEXTURE_2D);
else
@ -496,7 +469,7 @@ void Gfx::CGLDevice::SetTextureEnabled(int index, bool enabled)
bool Gfx::CGLDevice::GetTextureEnabled(int index)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
return m_texturesEnabled[index];
}
@ -505,111 +478,137 @@ bool Gfx::CGLDevice::GetTextureEnabled(int index)
Sets the texture parameters for the given texture stage.
If the given texture was not set (bound) yet, nothing happens.
The settings are remembered, even if texturing is disabled at the moment. */
void Gfx::CGLDevice::SetTextureParams(int index, const Gfx::TextureParams &params)
void Gfx::CGLDevice::SetTextureStageParams(int index, const Gfx::TextureStageParams &params)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
// Remember the settings
m_texturesParams[index] = params;
m_textureStageParams[index] = params;
// Don't actually do anything if texture not set
if (! m_textures[index].valid)
if (! m_currentTextures[index].valid)
return;
// Enable the given stage
glActiveTextureARB(GL_TEXTURE0_ARB + index);
glActiveTexture(GL_TEXTURE0 + index);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[index].id);
glBindTexture(GL_TEXTURE_2D, m_currentTextures[index].id);
// To save some trouble
if ( (params.colorOperation == Gfx::TEX_MIX_OPER_DEFAULT) &&
(params.alphaOperation == Gfx::TEX_MIX_OPER_DEFAULT) )
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
goto after_tex_operations;
}
// Selection of operation and arguments
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
// Only these modes of getting color & alpha are used
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
// Color operation
if (params.colorOperation == Gfx::TEX_MIX_OPER_MODULATE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB_ARB, GL_MODULATE);
if (params.colorOperation == Gfx::TEX_MIX_OPER_DEFAULT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB, GL_MODULATE);
goto after_tex_color;
}
else if (params.colorOperation == Gfx::TEX_MIX_OPER_REPLACE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB, GL_REPLACE);
else if (params.colorOperation == Gfx::TEX_MIX_OPER_MODULATE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB, GL_MODULATE);
else if (params.colorOperation == Gfx::TEX_MIX_OPER_ADD)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB, GL_ADD);
else if (params.colorOperation == Gfx::TEX_MIX_OPER_SUBTRACT)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_RGB, GL_SUBTRACT);
else assert(false);
// Color arg1
if (params.colorArg1 == Gfx::TEX_MIX_ARG_CURRENT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); // that's right - stupid D3D enum values
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
}
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
}
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_DIFFUSE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR); // here as well
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
}
if (params.colorArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_FACTOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
else assert(false);
// Color arg2
if (params.colorArg2 == Gfx::TEX_MIX_ARG_CURRENT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
}
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
}
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_DIFFUSE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
}
if (params.colorArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_FACTOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
else assert(false);
after_tex_color:
// Alpha operation
if (params.alphaOperation == Gfx::TEX_MIX_OPER_MODULATE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
if (params.alphaOperation == Gfx::TEX_MIX_OPER_DEFAULT)
{
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
goto after_tex_operations;
}
else if (params.colorOperation == Gfx::TEX_MIX_OPER_REPLACE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA, GL_REPLACE);
else if (params.alphaOperation == Gfx::TEX_MIX_OPER_MODULATE)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA, GL_MODULATE);
else if (params.alphaOperation == Gfx::TEX_MIX_OPER_ADD)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA, GL_ADD);
else if (params.alphaOperation == Gfx::TEX_MIX_OPER_SUBTRACT)
glTexEnvi(GL_TEXTURE_2D, GL_COMBINE_ALPHA, GL_SUBTRACT);
else assert(false);
// Alpha arg1
if (params.alphaArg1 == Gfx::TEX_MIX_ARG_CURRENT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
}
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_DIFFUSE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
if (params.alphaArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_FACTOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
else assert(false);
// Alpha arg2
if (params.alphaArg2 == Gfx::TEX_MIX_ARG_CURRENT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
}
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
}
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_DIFFUSE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
}
if (params.alphaArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_FACTOR)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
else assert(false);
after_tex_operations:
if (params.wrapS == Gfx::TEX_WRAP_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
else if (params.wrapS == Gfx::TEX_WRAP_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
else assert(false);
if (params.wrapT == Gfx::TEX_WRAP_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
else if (params.wrapT == Gfx::TEX_WRAP_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else assert(false);
// Disable the stage if it is set so
@ -617,21 +616,21 @@ void Gfx::CGLDevice::SetTextureParams(int index, const Gfx::TextureParams &param
glDisable(GL_TEXTURE_2D);
}
Gfx::TextureParams Gfx::CGLDevice::GetTextureParams(int index)
Gfx::TextureStageParams Gfx::CGLDevice::GetTextureStageParams(int index)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
assert(index < (int)m_currentTextures.size());
return m_texturesParams[index];
return m_textureStageParams[index];
}
void Gfx::CGLDevice::SetTextureFactor(const Gfx::Color &color)
{
// Needs to be set for all texture stages
for (int index = 0; index < (int)m_textures.size(); ++index)
for (int index = 0; index < (int)m_currentTextures.size(); ++index)
{
// Activate stage
glActiveTextureARB(GL_TEXTURE0_ARB + index);
glActiveTexture(GL_TEXTURE0 + index);
glEnable(GL_TEXTURE_2D);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color.Array());
@ -645,7 +644,7 @@ void Gfx::CGLDevice::SetTextureFactor(const Gfx::Color &color)
Gfx::Color Gfx::CGLDevice::GetTextureFactor()
{
// Get from 1st stage (should be the same for all stages)
glActiveTextureARB(GL_TEXTURE0_ARB);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
GLfloat color[4] = { 0.0f };
@ -672,7 +671,7 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const Vertex *vertic
for (int i = 0; i < vertexCount; ++i)
{
glNormal3fv(const_cast<GLfloat*>(vertices[i].normal.Array()));
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
}
@ -692,7 +691,7 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexCol
{
glColor4fv(const_cast<GLfloat*>(vertices[i].color.Array()));
glSecondaryColor3fv(const_cast<GLfloat*>(vertices[i].specular.Array()));
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
}
@ -713,8 +712,8 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const VertexTex2 *ve
for (int i = 0; i < vertexCount; ++i)
{
glNormal3fv(const_cast<GLfloat*>(vertices[i].normal.Array()));
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glMultiTexCoord2fv(GL_TEXTURE1, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
}
@ -814,9 +813,9 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
m_texturing = enabled;
// Enable/disable stages with new setting
for (int index = 0; index < (int)m_textures.size(); ++index)
for (int index = 0; index < (int)m_currentTextures.size(); ++index)
{
glActiveTextureARB(GL_TEXTURE0_ARB + index);
glActiveTexture(GL_TEXTURE0 + index);
if (m_texturing && m_texturesEnabled[index])
glEnable(GL_TEXTURE_2D);
else

View File

@ -107,8 +107,8 @@ public:
virtual void SetTextureEnabled(int index, bool enabled);
virtual bool GetTextureEnabled(int index);
virtual void SetTextureParams(int index, const Gfx::TextureParams &params);
virtual Gfx::TextureParams GetTextureParams(int index);
virtual void SetTextureStageParams(int index, const Gfx::TextureStageParams &params);
virtual Gfx::TextureStageParams GetTextureStageParams(int index);
virtual void SetTextureFactor(const Gfx::Color &color);
virtual Gfx::Color GetTextureFactor();
@ -153,6 +153,7 @@ public:
virtual Gfx::FillMode GetFillMode();
private:
//! Updates internal modelview matrix
void UpdateModelviewMatrix();
private:
@ -181,11 +182,11 @@ private:
//! Whether texturing is enabled in general
bool m_texturing;
//! Current textures; \c NULL value means unassigned
std::vector<Gfx::Texture> m_textures;
std::vector<Gfx::Texture> m_currentTextures;
//! Current texture stages enable status
std::vector<bool> m_texturesEnabled;
//! Current texture params
std::vector<Gfx::TextureParams> m_texturesParams;
std::vector<Gfx::TextureStageParams> m_textureStageParams;
//! Set of all created textures
std::set<Gfx::Texture> m_allTextures;

View File

@ -73,7 +73,6 @@ void LoadTexture(Gfx::CGLDevice *device, const std::string &name)
texCreateParams.format = Gfx::TEX_IMG_BGRA;
texCreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
texCreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
texCreateParams.wrapT = Gfx::TEX_WRAP_CLAMP;
tex = device->CreateTexture(&img, texCreateParams);
}
@ -139,16 +138,6 @@ void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile)
device->SetTextureEnabled(0, true);
device->SetTextureEnabled(1, true);
Gfx::TextureParams tex1Params;
tex1Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
tex1Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
device->SetTextureParams(0, tex1Params);
Gfx::TextureParams tex2Params;
tex2Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
tex2Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
device->SetTextureParams(1, tex2Params);
device->SetMaterial(triangles[i].material);
tri[0] = triangles[i].p1;

View File

@ -10,9 +10,14 @@
void Init(Gfx::CGLDevice *device)
{
device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false);
device->SetShadeModel(Gfx::SHADE_SMOOTH);
device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false);
device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
device->SetTextureEnabled(0, true);
device->SetTextureEnabled(1, true);
CImage img1;
if (! img1.Load("tex1.png"))
{
@ -31,32 +36,18 @@ void Init(Gfx::CGLDevice *device)
tex1CreateParams.format = Gfx::TEX_IMG_RGBA;
tex1CreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
tex1CreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
tex1CreateParams.wrapT = Gfx::TEX_WRAP_CLAMP;
Gfx::TextureCreateParams tex2CreateParams;
tex2CreateParams.mipmap = true;
tex2CreateParams.format = Gfx::TEX_IMG_RGBA;
tex2CreateParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST;
tex2CreateParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
tex2CreateParams.wrapS = Gfx::TEX_WRAP_CLAMP;
Gfx::Texture tex1 = device->CreateTexture(&img1, tex1CreateParams);
Gfx::Texture tex2 = device->CreateTexture(&img2, tex2CreateParams);
device->SetTexture(0, tex1);
device->SetTexture(1, tex2);
Gfx::TextureParams tex1Params;
tex1Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
tex1Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
device->SetTextureParams(0, tex1Params);
Gfx::TextureParams tex2Params;
tex2Params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
tex2Params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
device->SetTextureParams(1, tex2Params);
device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
}
void Render(Gfx::CGLDevice *device)
@ -84,6 +75,16 @@ void Render(Gfx::CGLDevice *device)
Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)),
};
Gfx::TextureStageParams tex1StageParams;
tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
device->SetTextureStageParams(0, tex1StageParams);
Gfx::TextureStageParams tex2StageParams;
tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
device->SetTextureStageParams(1, tex2StageParams);
Math::Matrix t;
Math::LoadTranslationMatrix(t, Math::Vector(-4.0f, 4.0f, 0.0f));
device->SetTransform(Gfx::TRANSFORM_VIEW, t);
@ -101,12 +102,12 @@ void Render(Gfx::CGLDevice *device)
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
device->SetTextureEnabled(0, true);
device->SetTextureEnabled(1, true);
Math::LoadTranslationMatrix(t, Math::Vector( 0.0f, -4.0f, 0.0f));
device->SetTransform(Gfx::TRANSFORM_VIEW, t);
device->SetTextureEnabled(0, true);
device->SetTextureEnabled(1, true);
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
device->EndScene();