Multitexturing support
- added CImage class for loading/saving images and a simple test for it - added libpng library to build - added Gfx::Texture struct - updated the Gfx::CDevice interface to include new features - implemented the new features in Gfx::CGLDevicedev-ui
parent
d9c5a439d0
commit
f95df35dc5
|
@ -8,6 +8,7 @@ project(colobot C CXX)
|
|||
find_package(OpenGL REQUIRED)
|
||||
find_package(SDL REQUIRED)
|
||||
find_package(SDL_image REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
# TODO: check for SDL version. Should be >= 1.2.10
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ app/app.cpp
|
|||
app/main.cpp
|
||||
app/system.cpp
|
||||
common/event.cpp
|
||||
common/image.cpp
|
||||
common/iman.cpp
|
||||
# common/metafile.cpp
|
||||
# common/misc.cpp
|
||||
|
@ -150,10 +151,16 @@ set(LIBS
|
|||
${SDL_LIBRARY}
|
||||
${SDLIMAGE_LIBRARY}
|
||||
${OPENGL_LIBRARY}
|
||||
${PNG_LIBRARIES}
|
||||
#CBot -- not yet WinAPI-independent
|
||||
)
|
||||
|
||||
include_directories(. ${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(. ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${SDL_INCLUDE_DIR}
|
||||
${SDL_IMAGE_INCLUDE_DIR}
|
||||
${SDLTTF_INCLUDE_DIR}
|
||||
${PNG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot)
|
||||
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * 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/.
|
||||
|
||||
// image.cpp
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_image.h>
|
||||
#include <png.h>
|
||||
|
||||
|
||||
/* <---------------------------------------------------------------> */
|
||||
|
||||
/* The following code is from savesurf program by Angelo "Encelo" Theodorou
|
||||
Source: http://encelo.netsons.org/old/sdl/
|
||||
The code was refactored and modified slightly to fit the needs.
|
||||
The copyright information below is kept unchanged. */
|
||||
|
||||
|
||||
/* SaveSurf: an example on how to save a SDLSurface in PNG
|
||||
Copyright (C) 2006 Angelo "Encelo" Theodorou
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
NOTE:
|
||||
|
||||
This program is part of "Mars, Land of No Mercy" SDL examples,
|
||||
you can find other examples on http://marsnomercy.org
|
||||
*/
|
||||
|
||||
std::string PNG_ERROR = "";
|
||||
|
||||
void PNGUserError(png_structp ctx, png_const_charp str)
|
||||
{
|
||||
PNG_ERROR = std::string(str);
|
||||
}
|
||||
|
||||
int PNGColortypeFromSurface(SDL_Surface *surface)
|
||||
{
|
||||
int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */
|
||||
|
||||
if (surface->format->palette)
|
||||
colortype |= PNG_COLOR_MASK_PALETTE;
|
||||
else if (surface->format->Amask)
|
||||
colortype |= PNG_COLOR_MASK_ALPHA;
|
||||
|
||||
return colortype;
|
||||
}
|
||||
|
||||
bool PNGSaveSurface(const char *filename, SDL_Surface *surf)
|
||||
{
|
||||
FILE *fp;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
int i, colortype;
|
||||
png_bytep *row_pointers;
|
||||
|
||||
PNG_ERROR = "";
|
||||
|
||||
/* Opening output file */
|
||||
fp = fopen(filename, "wb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
PNG_ERROR = std::string("Could not open file '") + std::string(filename) + std::string("' for saving");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initializing png structures and callbacks */
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNGUserError, NULL);
|
||||
if (png_ptr == NULL)
|
||||
return false;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL)
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
PNG_ERROR = "png_create_info_struct() error!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
colortype = PNGColortypeFromSurface(surf);
|
||||
png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
/* Writing the image */
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surf->h);
|
||||
for (i = 0; i < surf->h; i++)
|
||||
row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch;
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* Cleaning out... */
|
||||
free(row_pointers);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* <---------------------------------------------------------------> */
|
||||
|
||||
|
||||
CImage::CImage()
|
||||
{
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
CImage::~CImage()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
bool CImage::IsEmpty()
|
||||
{
|
||||
return m_data == NULL;
|
||||
}
|
||||
|
||||
void CImage::Free()
|
||||
{
|
||||
if (m_data != NULL)
|
||||
{
|
||||
if (m_data->surface != NULL)
|
||||
{
|
||||
SDL_FreeSurface(m_data->surface);
|
||||
m_data->surface = NULL;
|
||||
}
|
||||
delete m_data;
|
||||
m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ImageData* CImage::GetData()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
std::string CImage::GetError()
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
bool CImage::Load(const std::string& fileName)
|
||||
{
|
||||
if (! IsEmpty() )
|
||||
Free();
|
||||
|
||||
m_data = new ImageData();
|
||||
|
||||
m_error = "";
|
||||
|
||||
m_data->surface = IMG_Load(fileName.c_str());
|
||||
if (m_data->surface == NULL)
|
||||
{
|
||||
delete m_data;
|
||||
m_data = NULL;
|
||||
|
||||
m_error = std::string(IMG_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CImage::SavePNG(const std::string& fileName)
|
||||
{
|
||||
if (IsEmpty())
|
||||
{
|
||||
m_error = "Empty image!";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_error = "";
|
||||
|
||||
if (! PNGSaveSurface(fileName.c_str(), m_data->surface) )
|
||||
{
|
||||
m_error = PNG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * 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/.
|
||||
|
||||
// image.h
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
// Forward declaration without including headers to clutter the code
|
||||
struct SDL_Surface;
|
||||
|
||||
//! Implementation-specific image data
|
||||
/** Note that the struct has no destructor and the surface
|
||||
will not be freed at destruction. */
|
||||
struct ImageData
|
||||
{
|
||||
//! SDL surface with image data
|
||||
SDL_Surface* surface;
|
||||
|
||||
ImageData() { surface = NULL; }
|
||||
};
|
||||
|
||||
/**
|
||||
\class CImage
|
||||
\brief Image loaded from file
|
||||
|
||||
Wrapper around SDL_Image library to load images. Also contains
|
||||
function for saving images to PNG.
|
||||
*/
|
||||
class CImage
|
||||
{
|
||||
private:
|
||||
//! Blocked!
|
||||
CImage(const CImage &other) {}
|
||||
//! Blocked!
|
||||
void operator=(const CImage &other) {}
|
||||
|
||||
public:
|
||||
//! Constructs empty image (with NULL data)
|
||||
CImage();
|
||||
//! Destroys image, calling Free()
|
||||
virtual ~CImage();
|
||||
|
||||
//! Frees the allocated image data
|
||||
void Free();
|
||||
|
||||
//! Returns whether the image is empty (has NULL data)
|
||||
bool IsEmpty();
|
||||
|
||||
//! Returns the image data; if empty - returns NULL
|
||||
ImageData* GetData();
|
||||
|
||||
//! Loads an image from the specified file
|
||||
bool Load(const std::string &fileName);
|
||||
|
||||
//! Saves the image to the specified file in PNG format
|
||||
bool SavePNG(const std::string &fileName);
|
||||
|
||||
//! Returns the last error
|
||||
std::string GetError();
|
||||
|
||||
private:
|
||||
//! Last encountered error
|
||||
std::string m_error;
|
||||
//! Image data
|
||||
ImageData* m_data;
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(CMAKE_BUILD_TYPE debug)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0")
|
||||
|
||||
add_executable(image_test ../image.cpp image_test.cpp)
|
|
@ -0,0 +1,34 @@
|
|||
#include "../image.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* For now, just a simple test: loading a file from image
|
||||
* and saving it to another in PNG. */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Usage: %s in_image out_image\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CImage image;
|
||||
|
||||
if (! image.Load(argv[1]))
|
||||
{
|
||||
std::string err = image.GetError();
|
||||
printf("Error loading '%s': %s\n", err.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! image.SavePNG(argv[2]))
|
||||
{
|
||||
std::string err = image.GetError();
|
||||
printf("Error saving PNG '%s': %s\n", err.c_str());
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -31,3 +31,20 @@ void Gfx::DeviceConfig::LoadDefault()
|
|||
doubleBuf = true;
|
||||
noFrame = false;
|
||||
}
|
||||
|
||||
void Gfx::TextureParams::LoadDefault()
|
||||
{
|
||||
minFilter = Gfx::TEX_MIN_FILTER_NEAREST;
|
||||
magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
|
||||
|
||||
wrapS = Gfx::TEX_WRAP_REPEAT;
|
||||
wrapT = Gfx::TEX_WRAP_REPEAT;
|
||||
|
||||
colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
|
||||
colorArg1 = Gfx::TEX_MIX_ARG_CURRENT;
|
||||
colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
|
||||
|
||||
alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
|
||||
alphaArg1 = Gfx::TEX_MIX_ARG_CURRENT;
|
||||
alphaArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
class CImage;
|
||||
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
|
@ -144,6 +147,15 @@ enum CullMode
|
|||
CULL_CCW
|
||||
};
|
||||
|
||||
/**
|
||||
\enum ShadeModel
|
||||
\brief Shade model used in rendering */
|
||||
enum ShadeModel
|
||||
{
|
||||
SHADE_FLAT,
|
||||
SHADE_SMOOTH
|
||||
};
|
||||
|
||||
/**
|
||||
\enum FillMode
|
||||
\brief Polygon fill mode */
|
||||
|
@ -169,6 +181,147 @@ enum PrimitiveType
|
|||
PRIMITIVE_TRIANGLE_STRIP
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TexMinFilter
|
||||
\brief Minification texture filter
|
||||
|
||||
Corresponds to OpenGL modes but should translate to DirectX too. */
|
||||
enum TexMinFilter
|
||||
{
|
||||
TEX_MIN_FILTER_NEAREST,
|
||||
TEX_MIN_FILTER_LINEAR,
|
||||
TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST,
|
||||
TEX_MIN_FILTER_LINEAR_MIPMAP_NEAREST,
|
||||
TEX_MIN_FILTER_NEAREST_MIPMAP_LINEAR,
|
||||
TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TexMagFilter
|
||||
\brief Magnification texture filter */
|
||||
enum TexMagFilter
|
||||
{
|
||||
TEX_MAG_FILTER_NEAREST,
|
||||
TEX_MAG_FILTER_LINEAR
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TexWrapMode
|
||||
\brief Wrapping mode for texture coords */
|
||||
enum TexWrapMode
|
||||
{
|
||||
TEX_WRAP_CLAMP,
|
||||
TEX_WRAP_REPEAT
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TexMixOperation
|
||||
\brief Multitexture mixing operation
|
||||
*/
|
||||
enum TexMixOperation
|
||||
{
|
||||
TEX_MIX_OPER_MODULATE,
|
||||
TEX_MIX_OPER_ADD
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TexMixArgument
|
||||
\brief Multitexture mixing argument
|
||||
*/
|
||||
enum TexMixArgument
|
||||
{
|
||||
TEX_MIX_ARG_CURRENT,
|
||||
TEX_MIX_ARG_TEXTURE,
|
||||
TEX_MIX_ARG_DIFFUSE,
|
||||
TEX_MIX_ARG_FACTOR
|
||||
};
|
||||
|
||||
/**
|
||||
\enum TextureParams
|
||||
\brief Parameters for texture creation
|
||||
*/
|
||||
struct TextureParams
|
||||
{
|
||||
//! Minification filter
|
||||
Gfx::TexMinFilter minFilter;
|
||||
//! Magnification filter
|
||||
Gfx::TexMagFilter magFilter;
|
||||
//! Wrap S coord mode
|
||||
Gfx::TexWrapMode wrapS;
|
||||
//! Wrap T coord mode
|
||||
Gfx::TexWrapMode wrapT;
|
||||
//! Mixing operation done on color values
|
||||
Gfx::TexMixOperation colorOperation;
|
||||
//! 1st argument of color operations
|
||||
Gfx::TexMixArgument colorArg1;
|
||||
//! 2nd argument of color operations
|
||||
Gfx::TexMixArgument colorArg2;
|
||||
//! Mixing operation done on alpha values
|
||||
Gfx::TexMixOperation alphaOperation;
|
||||
//! 1st argument of alpha operations
|
||||
Gfx::TexMixArgument alphaArg1;
|
||||
//! 2nd argument of alpha operations
|
||||
Gfx::TexMixArgument alphaArg2;
|
||||
|
||||
//! Constructor; calls LoadDefault()
|
||||
TextureParams()
|
||||
{ LoadDefault(); }
|
||||
|
||||
//! Loads the default values
|
||||
void LoadDefault();
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Notes for rewriting DirectX code:
|
||||
|
||||
>> SetRenderState() translates to many functions depending on param
|
||||
|
||||
D3DRENDERSTATE_ALPHABLENDENABLE -> SetRenderState() with RENDER_STATE_BLENDING
|
||||
D3DRENDERSTATE_ALPHAFUNC -> SetAlphaTestFunc() func
|
||||
D3DRENDERSTATE_ALPHAREF -> SetAlphaTestFunc() ref
|
||||
D3DRENDERSTATE_ALPHATESTENABLE -> SetRenderState() with RENDER_STATE_ALPHA_TEST
|
||||
D3DRENDERSTATE_AMBIENT -> SetGlobalAmbient()
|
||||
D3DRENDERSTATE_CULLMODE -> SetCullMode()
|
||||
D3DRENDERSTATE_DESTBLEND -> SetBlendFunc() dest blending func
|
||||
D3DRENDERSTATE_DITHERENABLE -> SetRenderState() with RENDER_STATE_DITHERING
|
||||
D3DRENDERSTATE_FILLMODE -> SetFillMode()
|
||||
D3DRENDERSTATE_FOGCOLOR -> SetFogParams()
|
||||
D3DRENDERSTATE_FOGENABLE -> SetRenderState() with RENDER_STATE_FOG
|
||||
D3DRENDERSTATE_FOGEND -> SetFogParams()
|
||||
D3DRENDERSTATE_FOGSTART -> SetFogParams()
|
||||
D3DRENDERSTATE_FOGVERTEXMODE -> SetFogParams() fog model
|
||||
D3DRENDERSTATE_LIGHTING -> SetRenderState() with RENDER_STATE_LIGHTING
|
||||
D3DRENDERSTATE_SHADEMODE -> SetShadeModel()
|
||||
D3DRENDERSTATE_SPECULARENABLE -> doesn't matter (always enabled)
|
||||
D3DRENDERSTATE_SRCBLEND -> SetBlendFunc() src blending func
|
||||
D3DRENDERSTATE_TEXTUREFACTOR -> SetTextureFactor()
|
||||
D3DRENDERSTATE_ZBIAS -> SetDepthBias()
|
||||
D3DRENDERSTATE_ZENABLE -> SetRenderState() with RENDER_STATE_DEPTH_TEST
|
||||
D3DRENDERSTATE_ZFUNC -> SetDepthTestFunc()
|
||||
D3DRENDERSTATE_ZWRITEENABLE -> SetRenderState() with RENDER_STATE_DEPTH_WRITE
|
||||
|
||||
|
||||
>> SetTextureStageState() translates to SetTextureParams()
|
||||
|
||||
Params from enum in struct TextureParams
|
||||
D3DTSS_ADDRESS -> Gfx::TexWrapMode wrapS, wrapT
|
||||
D3DTSS_ALPHAARG1 -> Gfx::TexMixArgument alphaArg1
|
||||
D3DTSS_ALPHAARG2 -> Gfx::TexMixArgument alphaArg2
|
||||
D3DTSS_ALPHAOP -> Gfx::TexMixOperation alphaOperation
|
||||
D3DTSS_COLORARG1 -> Gfx::TexMixArgument colorArg1
|
||||
D3DTSS_COLORARG2 -> Gfx::TexMixArgument colorArg2
|
||||
D3DTSS_COLOROP -> Gfx::TexMixOperation colorOperation
|
||||
D3DTSS_MAGFILTER -> Gfx::TexMagFilter magFilter
|
||||
D3DTSS_MINFILTER -> Gfx::TexMinFilter minFilter
|
||||
D3DTSS_TEXCOORDINDEX -> doesn't matter (texture coords are set explicitly by glMultiTexCoordARB*)
|
||||
|
||||
Note that D3DTSS_ALPHAOP or D3DTSS_COLOROP set to D3DTOP_DISABLE must translate to disabling the whole texture stage.
|
||||
In DirectX, you shouldn't mix enabling one and disabling the other.
|
||||
Also, if previous stage is disabled in DirectX, the later ones are disabled, too. In OpenGL, that is not the case.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
\class CDevice
|
||||
\brief Abstract interface of graphics device
|
||||
|
@ -226,20 +379,33 @@ public:
|
|||
//! Returns the current enable state of light at given index
|
||||
virtual bool GetLightEnabled(int index) = 0;
|
||||
|
||||
// TODO:
|
||||
// virtual Gfx::Texture* CreateTexture(CImage *image) = 0;
|
||||
// virtual void DestroyTexture(Gfx::Texture *texture) = 0;
|
||||
//! Creates a texture from image; the image can be safely removed after that
|
||||
virtual Gfx::Texture* CreateTexture(CImage *image, bool alpha, bool mipMap) = 0;
|
||||
//! Deletes a given texture, freeing it from video memory
|
||||
virtual void DestroyTexture(Gfx::Texture *texture) = 0;
|
||||
//! Deletes all textures created so far
|
||||
virtual void DestroyAllTextures() = 0;
|
||||
|
||||
//! Returns the maximum number of multitexture units
|
||||
//! Returns the maximum number of multitexture stages
|
||||
virtual int GetMaxTextureCount() = 0;
|
||||
//! Sets the (multi)texture at given index
|
||||
virtual void SetTexture(int index, Gfx::Texture *texture) = 0;
|
||||
//! Returns the (multi)texture at given index
|
||||
virtual Gfx::Texture* GetTexture(int index) = 0;
|
||||
//! Enables/disables the given texture stage
|
||||
virtual void SetTextureEnabled(int index, bool enabled) = 0;
|
||||
//! Returns the current enable state of given texture stage
|
||||
virtual bool GetTextureEnabled(int index) = 0;
|
||||
|
||||
// TODO:
|
||||
// virtual void GetTextureStageState() = 0;
|
||||
// virtual void SetTextureStageState() = 0;
|
||||
//! Sets the current params of texture with given index
|
||||
virtual void SetTextureParams(int index, const Gfx::TextureParams ¶ms) = 0;
|
||||
//! Returns the current params of texture with given index
|
||||
virtual Gfx::TextureParams GetTextureParams(int index) = 0;
|
||||
|
||||
//! Sets the texture factor to the given color value
|
||||
virtual void SetTextureFactor(Gfx::Color &color) = 0;
|
||||
//! Returns the current texture factor
|
||||
virtual Gfx::Color GetTextureFactor() = 0;
|
||||
|
||||
//! Renders primitive composed of vertices with single texture
|
||||
virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::Vertex *vertices, int vertexCount) = 0;
|
||||
|
@ -297,6 +463,11 @@ public:
|
|||
//! Returns the current cull mode
|
||||
virtual Gfx::CullMode GetCullMode() = 0;
|
||||
|
||||
//! Sets the shade model
|
||||
virtual void SetShadeModel(Gfx::ShadeModel model) = 0;
|
||||
//! Returns the current shade model
|
||||
virtual Gfx::ShadeModel GetShadeModel() = 0;
|
||||
|
||||
//! Sets the current fill mode
|
||||
virtual void SetFillMode(Gfx::FillMode mode) = 0;
|
||||
//! Returns the current fill mode
|
||||
|
|
|
@ -20,9 +20,16 @@
|
|||
|
||||
namespace Gfx {
|
||||
|
||||
/** \struct Texture*/
|
||||
struct Texture
|
||||
{
|
||||
// TODO
|
||||
//! Whether the texture was loaded
|
||||
bool valid;
|
||||
//! Id of the texture in graphics engine
|
||||
unsigned int id;
|
||||
|
||||
Texture()
|
||||
{ valid = false; id = 0; }
|
||||
};
|
||||
|
||||
}; // namespace Gfx
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
// gldevice.cpp
|
||||
|
||||
#include "common/image.h"
|
||||
#include "graphics/opengl/gldevice.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
@ -30,21 +31,13 @@ namespace Gfx {
|
|||
|
||||
struct GLDevicePrivate
|
||||
{
|
||||
void (APIENTRY* glMultiTexCoord1fARB)(GLenum target, GLfloat s);
|
||||
void (APIENTRY* glMultiTexCoord2fARB)(GLenum target, GLfloat s, GLfloat t);
|
||||
void (APIENTRY* glMultiTexCoord3fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
|
||||
void (APIENTRY* glMultiTexCoord4fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
|
||||
void (APIENTRY* glActiveTextureARB)(GLenum texture);
|
||||
void (APIENTRY* glClientActiveTextureARB)(GLenum texture);
|
||||
|
||||
GLDevicePrivate()
|
||||
{
|
||||
glMultiTexCoord1fARB = NULL;
|
||||
glMultiTexCoord2fARB = NULL;
|
||||
glMultiTexCoord3fARB = NULL;
|
||||
glMultiTexCoord4fARB = NULL;
|
||||
glActiveTextureARB = NULL;
|
||||
glClientActiveTextureARB = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -71,6 +64,7 @@ Gfx::CGLDevice::CGLDevice()
|
|||
{
|
||||
m_private = new Gfx::GLDevicePrivate();
|
||||
m_wasInit = false;
|
||||
m_texturing = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,18 +86,10 @@ std::string Gfx::CGLDevice::GetError()
|
|||
|
||||
bool Gfx::CGLDevice::Create()
|
||||
{
|
||||
m_wasInit = true;
|
||||
|
||||
// TODO: move to functions?
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
/* 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));
|
||||
|
||||
|
@ -119,37 +105,58 @@ bool Gfx::CGLDevice::Create()
|
|||
return false;
|
||||
}
|
||||
|
||||
m_private->glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
||||
m_private->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
||||
|
||||
if ((m_private->glMultiTexCoord2fARB == NULL) || (m_private->glActiveTextureARB == NULL))
|
||||
{
|
||||
m_error = "Could not load extension functions, even though they seem supported";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_wasInit = true;
|
||||
|
||||
// This is mostly done in all modern hardware by default
|
||||
// DirectX doesn't even allow the option to turn off perspective correction anymore
|
||||
// So turn it on permanently
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
|
||||
// Set just to be sure
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
m_lights = std::vector<Gfx::Light>(GL_MAX_LIGHTS, Gfx::Light());
|
||||
m_lightsEnabled = std::vector<bool> (GL_MAX_LIGHTS, false);
|
||||
|
||||
int maxTextures = 0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextures);
|
||||
m_textures = std::vector<Gfx::Texture*>(maxTextures, NULL);
|
||||
|
||||
m_lights = std::vector<Gfx::Light>(GL_MAX_LIGHTS, Gfx::Light());
|
||||
m_lightsEnabled = std::vector<bool>(GL_MAX_LIGHTS, false);
|
||||
|
||||
m_private->glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord1fARB");
|
||||
m_private->glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
||||
m_private->glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord3fARB");
|
||||
m_private->glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord4fARB");
|
||||
m_private->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
||||
m_private->glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB");
|
||||
m_textures = std::vector<Gfx::Texture*> (maxTextures, NULL);
|
||||
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
||||
m_texturesParams = std::vector<Gfx::TextureParams>(maxTextures, Gfx::TextureParams());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::Destroy()
|
||||
{
|
||||
m_private->glMultiTexCoord1fARB = NULL;
|
||||
m_private->glMultiTexCoord2fARB = NULL;
|
||||
m_private->glMultiTexCoord3fARB = NULL;
|
||||
m_private->glMultiTexCoord4fARB = NULL;
|
||||
m_private->glActiveTextureARB = NULL;
|
||||
m_private->glClientActiveTextureARB = NULL;
|
||||
|
||||
// Delete the remaining textures
|
||||
std::set<Gfx::Texture*>::iterator it;
|
||||
for (it = m_allTextures.begin(); it != m_allTextures.end(); ++it)
|
||||
delete *it;
|
||||
m_allTextures.clear();
|
||||
// Should not be strictly necessary, but just in case
|
||||
DestroyAllTextures();
|
||||
|
||||
m_lights.clear();
|
||||
m_lightsEnabled.clear();
|
||||
|
||||
m_textures.clear();
|
||||
m_texturesEnabled.clear();
|
||||
m_texturesParams.clear();
|
||||
|
||||
m_wasInit = false;
|
||||
}
|
||||
|
@ -177,7 +184,7 @@ void Gfx::CGLDevice::Clear()
|
|||
|
||||
void Gfx::CGLDevice::SetTransform(Gfx::TransformType type, const Math::Matrix &matrix)
|
||||
{
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
{
|
||||
m_worldMat = matrix;
|
||||
m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
|
||||
|
@ -205,7 +212,7 @@ void Gfx::CGLDevice::SetTransform(Gfx::TransformType type, const Math::Matrix &m
|
|||
|
||||
const Math::Matrix& Gfx::CGLDevice::GetTransform(Gfx::TransformType type)
|
||||
{
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
return m_worldMat;
|
||||
else if (type == Gfx::TRANSFORM_VIEW)
|
||||
return m_viewMat;
|
||||
|
@ -219,7 +226,7 @@ const Math::Matrix& Gfx::CGLDevice::GetTransform(Gfx::TransformType type)
|
|||
|
||||
void Gfx::CGLDevice::MultiplyTransform(Gfx::TransformType type, const Math::Matrix &matrix)
|
||||
{
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
if (type == Gfx::TRANSFORM_WORLD)
|
||||
{
|
||||
m_worldMat = Math::MultiplyMatrices(m_worldMat, matrix);
|
||||
m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
|
||||
|
@ -306,7 +313,7 @@ const Gfx::Light& Gfx::CGLDevice::GetLight(int index)
|
|||
void Gfx::CGLDevice::SetLightEnabled(int index, bool enabled)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_lightsEnabled.size());
|
||||
assert(index < (int)m_lights.size());
|
||||
|
||||
m_lightsEnabled[index] = enabled;
|
||||
|
||||
|
@ -321,11 +328,102 @@ bool Gfx::CGLDevice::GetLightEnabled(int index)
|
|||
return m_lightsEnabled[index];
|
||||
}
|
||||
|
||||
Gfx::Texture* Gfx::CGLDevice::CreateTexture(CImage *image, bool alpha, bool mipMap)
|
||||
{
|
||||
Gfx::Texture *result = new Gfx::Texture();
|
||||
|
||||
// Texturing must be enabled, so enable 1st texture stage
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glGenTextures(1, &result->id);
|
||||
glBindTexture(GL_TEXTURE_2D, result->id);
|
||||
|
||||
GLenum sourceFormat = 0;
|
||||
if (alpha)
|
||||
sourceFormat = GL_RGBA;
|
||||
else
|
||||
sourceFormat = GL_RGB;
|
||||
|
||||
ImageData *data = image->GetData();
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
if (mipMap)
|
||||
{
|
||||
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, data->surface->w,
|
||||
data->surface->h, sourceFormat, GL_UNSIGNED_BYTE,
|
||||
data->surface->pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data->surface->w, data->surface->h,
|
||||
0, sourceFormat, GL_UNSIGNED_BYTE, data->surface->pixels);
|
||||
}
|
||||
|
||||
// Restore previous setup of 1st texture stage
|
||||
RestoreTextureStage(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::DestroyTexture(Gfx::Texture *texture)
|
||||
{
|
||||
std::set<Gfx::Texture*>::iterator it = m_allTextures.find(texture);
|
||||
if (it != m_allTextures.end())
|
||||
m_allTextures.erase(it);
|
||||
|
||||
glDeleteTextures(1, &texture->id);
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::DestroyAllTextures()
|
||||
{
|
||||
std::set<Gfx::Texture*> allCopy = m_allTextures;
|
||||
std::set<Gfx::Texture*>::iterator it;
|
||||
for (it = allCopy.begin(); it != allCopy.end(); ++it)
|
||||
{
|
||||
DestroyTexture(*it);
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
int Gfx::CGLDevice::GetMaxTextureCount()
|
||||
{
|
||||
return m_textures.size();
|
||||
}
|
||||
|
||||
/**
|
||||
If \a texture is \c NULL or invalid, unbinds the given texture.
|
||||
If valid, binds the texture and enables the given texture stage.
|
||||
The setting is remembered, even if texturing is disabled at the moment. */
|
||||
void Gfx::CGLDevice::SetTexture(int index, Gfx::Texture *texture)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_textures.size());
|
||||
|
||||
// Enable the given texture stage
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
if ((texture == NULL) || (! texture->valid))
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // unbind texture
|
||||
m_textures[index] = NULL; // remember the changes
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id); // bind the texture
|
||||
m_textures[index] = texture; // remember the changes
|
||||
SetTextureParams(index, m_texturesParams[index]); // texture params need to be re-set for the new texture
|
||||
}
|
||||
|
||||
// Disable the stage if it is set so
|
||||
if ( (! m_texturing) || (! m_texturesEnabled[index]) )
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the previously assigned texture or \c NULL if the given stage is not enabled. */
|
||||
Gfx::Texture* Gfx::CGLDevice::GetTexture(int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
|
@ -334,14 +432,224 @@ Gfx::Texture* Gfx::CGLDevice::GetTexture(int index)
|
|||
return m_textures[index];
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::SetTexture(int index, Gfx::Texture *texture)
|
||||
void Gfx::CGLDevice::SetTextureEnabled(int index, bool enabled)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_textures.size());
|
||||
|
||||
m_textures[index] = texture;
|
||||
m_texturesEnabled[index] = enabled;
|
||||
|
||||
// TODO
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
if (enabled)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
else
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
bool Gfx::CGLDevice::GetTextureEnabled(int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_textures.size());
|
||||
|
||||
return m_texturesEnabled[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 ¶ms)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_textures.size());
|
||||
|
||||
// Remember the settings
|
||||
m_texturesParams[index] = params;
|
||||
|
||||
// Enable the given stage
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
GLint minF = 0;
|
||||
if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST) minF = GL_NEAREST;
|
||||
else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR) minF = GL_LINEAR;
|
||||
else if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST) minF = GL_NEAREST_MIPMAP_NEAREST;
|
||||
else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_NEAREST) minF = GL_LINEAR_MIPMAP_NEAREST;
|
||||
else if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_LINEAR) minF = GL_NEAREST_MIPMAP_LINEAR;
|
||||
else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR) minF = GL_LINEAR_MIPMAP_LINEAR;
|
||||
else assert(false);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minF);
|
||||
|
||||
GLint magF = 0;
|
||||
if (params.magFilter == Gfx::TEX_MAG_FILTER_NEAREST) magF = GL_NEAREST;
|
||||
else if (params.magFilter == Gfx::TEX_MAG_FILTER_LINEAR) magF = GL_LINEAR;
|
||||
else assert(false);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
// Selection of operation and arguments
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
// Color operation
|
||||
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, GL_ADD);
|
||||
else assert(false);
|
||||
|
||||
// Color arg1
|
||||
if (params.colorArg1 == Gfx::TEX_MIX_ARG_CURRENT)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); // that's right - stupid D3D enum values
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else if (params.colorArg1 == Gfx::TEX_MIX_ARG_DIFFUSE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR); // here as well
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else assert(false);
|
||||
|
||||
// Color arg2
|
||||
if (params.colorArg2 == Gfx::TEX_MIX_ARG_CURRENT)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else if (params.colorArg2 == Gfx::TEX_MIX_ARG_DIFFUSE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
}
|
||||
else assert(false);
|
||||
|
||||
// Alpha operation
|
||||
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, GL_ADD);
|
||||
else assert(false);
|
||||
|
||||
// Alpha arg1
|
||||
if (params.alphaArg1 == Gfx::TEX_MIX_ARG_CURRENT)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, 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);
|
||||
}
|
||||
else assert(false);
|
||||
|
||||
// Alpha arg2
|
||||
if (params.alphaArg2 == Gfx::TEX_MIX_ARG_CURRENT)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_DIFFUSE)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
else assert(false);
|
||||
|
||||
// Disable the stage if it is set so
|
||||
if ( (! m_texturing) || (! m_texturesEnabled[index]) )
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
Gfx::TextureParams Gfx::CGLDevice::GetTextureParams(int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_textures.size());
|
||||
|
||||
return m_texturesParams[index];
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::SetTextureFactor(Gfx::Color &color)
|
||||
{
|
||||
// Needs to be set for all texture stages
|
||||
for (int index = 0; index < (int)m_textures.size(); ++index)
|
||||
{
|
||||
// Activate stage
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color.Array());
|
||||
|
||||
// Disable the stage if it is set so
|
||||
if ( (! m_texturing) || (! m_texturesEnabled[index]) )
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::Color Gfx::CGLDevice::GetTextureFactor()
|
||||
{
|
||||
// Get from 1st stage (should be the same for all stages)
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
GLfloat color[4] = { 0.0f };
|
||||
glGetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
|
||||
|
||||
// Disable the 1st stage if it is set so
|
||||
if ( (! m_texturing) || (! m_texturesEnabled[0]) )
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
return Gfx::Color(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::RestoreTextureStage(int index)
|
||||
{
|
||||
// Ensure that we're working with the right stage
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
if (m_textures[index] != NULL)
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures[index]->id); // bind to the previous texture
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // unbind
|
||||
|
||||
// Disable the stage if it is set so
|
||||
if ( (! m_texturing) || (! m_texturesEnabled[index]) )
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount)
|
||||
|
@ -374,7 +682,7 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vert
|
|||
|
||||
for (int i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
// TODO: specular?
|
||||
// TODO: specular through EXT_separate_specular_color?
|
||||
glColor4fv((GLfloat*)vertices[i].color.Array());
|
||||
glTexCoord2fv((GLfloat*)vertices[i].texCoord.Array());
|
||||
glVertex3fv((GLfloat*)vertices[i].coord.Array());
|
||||
|
@ -395,8 +703,8 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices
|
|||
for (int i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
glNormal3fv((GLfloat*) vertices[i].normal.Array());
|
||||
// TODO glMultiTexCoord2fARB(GL_TEXTURE0_ARB, vertices[i].texCoord.x, vertices[i].texCoord.y);
|
||||
// TODO glMultiTexCoord2fARB(GL_TEXTURE1_ARB, vertices[i].texCoord2.x, vertices[i].texCoord2.y);
|
||||
m_private->glMultiTexCoord2fARB(GL_TEXTURE0_ARB, vertices[i].texCoord.x, vertices[i].texCoord.y);
|
||||
m_private->glMultiTexCoord2fARB(GL_TEXTURE1_ARB, vertices[i].texCoord2.x, vertices[i].texCoord2.y);
|
||||
glVertex3fv((GLfloat*) vertices[i].coord.Array());
|
||||
}
|
||||
|
||||
|
@ -412,14 +720,26 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
|||
}
|
||||
else if (state == RENDER_STATE_TEXTURING)
|
||||
{
|
||||
m_texturing = enabled;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
// TODO multitexture
|
||||
// All enabled multitexture stages have to be enabled
|
||||
for (int index = 0; index < (int)m_textures.size(); ++index)
|
||||
{
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
if (m_texturesEnabled[index])
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
// All multitexture stages have to be disabled
|
||||
for (int index = 0; index < (int)m_textures.size(); ++index)
|
||||
{
|
||||
m_private->glActiveTextureARB(GL_TEXTURE0_ARB + index);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -445,12 +765,14 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
|||
|
||||
bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state)
|
||||
{
|
||||
if (state == RENDER_STATE_TEXTURING)
|
||||
return m_texturing;
|
||||
|
||||
GLenum flag = 0;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case Gfx::RENDER_STATE_DEPTH_WRITE: flag = GL_DEPTH_WRITEMASK; break;
|
||||
case Gfx::RENDER_STATE_TEXTURING: flag = GL_TEXTURE_2D; break;
|
||||
case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break;
|
||||
case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
|
||||
case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
|
||||
|
@ -602,7 +924,7 @@ void Gfx::CGLDevice::SetClearColor(Gfx::Color color)
|
|||
|
||||
Gfx::Color Gfx::CGLDevice::GetClearColor()
|
||||
{
|
||||
float color[4] = { 0.0f };
|
||||
GLfloat color[4] = { 0.0f };
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, color);
|
||||
return Gfx::Color(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
@ -614,7 +936,7 @@ void Gfx::CGLDevice::SetGlobalAmbient(Gfx::Color color)
|
|||
|
||||
Gfx::Color Gfx::CGLDevice::GetGlobalAmbient()
|
||||
{
|
||||
float color[4] = { 0.0f };
|
||||
GLfloat color[4] = { 0.0f };
|
||||
glGetFloatv(GL_LIGHT_MODEL_AMBIENT, color);
|
||||
return Gfx::Color(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
@ -662,6 +984,23 @@ Gfx::CullMode Gfx::CGLDevice::GetCullMode()
|
|||
return Gfx::CULL_CW;
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::SetShadeModel(Gfx::ShadeModel model)
|
||||
{
|
||||
if (model == Gfx::SHADE_FLAT) glShadeModel(GL_FLAT);
|
||||
else if (model == Gfx::SHADE_SMOOTH) glShadeModel(GL_SMOOTH);
|
||||
else assert(false);
|
||||
}
|
||||
|
||||
Gfx::ShadeModel Gfx::CGLDevice::GetShadeModel()
|
||||
{
|
||||
GLenum flag = 0;
|
||||
glGetIntegerv(GL_SHADE_MODEL, (GLint*)&flag);
|
||||
if (flag == GL_FLAT) return Gfx::SHADE_FLAT;
|
||||
else if (flag == GL_SMOOTH) return Gfx::SHADE_SMOOTH;
|
||||
else assert(false);
|
||||
return Gfx::SHADE_FLAT;
|
||||
}
|
||||
|
||||
void Gfx::CGLDevice::SetFillMode(Gfx::FillMode mode)
|
||||
{
|
||||
if (mode == Gfx::FILL_POINT) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||
|
@ -677,6 +1016,6 @@ Gfx::FillMode Gfx::CGLDevice::GetFillMode()
|
|||
if (flag == GL_POINT) return Gfx::FILL_POINT;
|
||||
else if (flag == GL_LINE) return Gfx::FILL_LINES;
|
||||
else if (flag == GL_FILL) return Gfx::FILL_FILL;
|
||||
else assert(false);
|
||||
else assert(false);
|
||||
return Gfx::FILL_POINT;
|
||||
}
|
||||
|
|
|
@ -97,9 +97,21 @@ public:
|
|||
virtual void SetLightEnabled(int index, bool enabled);
|
||||
virtual bool GetLightEnabled(int index);
|
||||
|
||||
virtual Gfx::Texture* CreateTexture(CImage *image, bool alpha, bool mipMap);
|
||||
virtual void DestroyTexture(Gfx::Texture *texture);
|
||||
virtual void DestroyAllTextures();
|
||||
|
||||
virtual int GetMaxTextureCount();
|
||||
virtual void SetTexture(int index, Gfx::Texture *texture);
|
||||
virtual void SetTexture(int index, Gfx::Texture *texture);
|
||||
virtual Gfx::Texture* GetTexture(int index);
|
||||
virtual void SetTextureEnabled(int index, bool enabled);
|
||||
virtual bool GetTextureEnabled(int index);
|
||||
|
||||
virtual void SetTextureParams(int index, const Gfx::TextureParams ¶ms);
|
||||
virtual Gfx::TextureParams GetTextureParams(int index);
|
||||
|
||||
virtual void SetTextureFactor(Gfx::Color &color);
|
||||
virtual Gfx::Color GetTextureFactor();
|
||||
|
||||
virtual void DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount);
|
||||
virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount);
|
||||
|
@ -133,6 +145,9 @@ public:
|
|||
virtual void SetCullMode(Gfx::CullMode mode);
|
||||
virtual Gfx::CullMode GetCullMode();
|
||||
|
||||
virtual void SetShadeModel(Gfx::ShadeModel model);
|
||||
virtual Gfx::ShadeModel GetShadeModel();
|
||||
|
||||
virtual void SetFillMode(Gfx::FillMode mode) ;
|
||||
virtual Gfx::FillMode GetFillMode();
|
||||
|
||||
|
@ -143,6 +158,7 @@ private:
|
|||
bool m_wasInit;
|
||||
//! Last encountered error
|
||||
std::string m_error;
|
||||
|
||||
//! Current world matrix
|
||||
Math::Matrix m_worldMat;
|
||||
//! Current view matrix
|
||||
|
@ -151,16 +167,29 @@ private:
|
|||
Math::Matrix m_modelviewMat;
|
||||
//! Current projection matrix
|
||||
Math::Matrix m_projectionMat;
|
||||
|
||||
//! The current material
|
||||
Gfx::Material m_material;
|
||||
|
||||
//! Current lights
|
||||
std::vector<Gfx::Light> m_lights;
|
||||
//! Current lights enable status
|
||||
std::vector<bool> m_lightsEnabled;
|
||||
//! Current textures
|
||||
|
||||
//! Whether texturing is enabled in general
|
||||
bool m_texturing;
|
||||
//! Current textures; \c NULL value means unassigned
|
||||
std::vector<Gfx::Texture*> m_textures;
|
||||
//! Current texture stages enable status
|
||||
std::vector<bool> m_texturesEnabled;
|
||||
//! Current texture params
|
||||
std::vector<Gfx::TextureParams> m_texturesParams;
|
||||
|
||||
//! Set of all created textures
|
||||
std::set<Gfx::Texture*> m_allTextures;
|
||||
|
||||
//! Restores the state of given texture stage to the previously saved settings
|
||||
void RestoreTextureStage(int index);
|
||||
};
|
||||
|
||||
}; // namespace Gfx
|
||||
|
|
Loading…
Reference in New Issue