1
0
forked from 0ad/0ad

- both tex.cpp and ogl_tex.cpp had functions named tex_* - confusing. renamed to ogl_tex* to disambiguate.

- ogl_tex_bind now supports multitexturing (avoids need to get id and
then bind manually)
- provide nicer API for querying texture properties (no longer one big
getter). improved GUI determination of texture alpha.
- renderer: another see-if-texture-has-alpha and fixed alpha map code
(wasn't checking if all are same size. only worked because the first map
was larger than the rest

This was SVN commit r2647.
This commit is contained in:
janwas 2005-09-02 02:54:02 +00:00
parent ed5041a301
commit 9ec828f6fd
8 changed files with 252 additions and 216 deletions

View File

@ -51,7 +51,7 @@ void CModel::ReleaseData()
m_pModelDef = CModelDefPtr();
Handle h = m_Texture.GetHandle();
tex_free(h);
ogl_tex_free(h);
m_Texture.SetHandle(0);
}

View File

@ -15,7 +15,7 @@
|
|
| Usage: The functions speak for themselves. Instantiate, then be
| sure to pass a loaded (using tex_load()) texture before
| sure to pass a loaded (using ogl_tex_load()) texture before
| calling Render().
|
| To do: TBA
@ -61,7 +61,7 @@ void CSprite::Render()
glTranslatef(m_translation.X, m_translation.Y, m_translation.Z);
glScalef(m_scale.X, m_scale.Y, m_scale.Z);
g_Renderer.BindTexture(0,tex_id(m_texture->GetHandle()));
ogl_tex_bind(m_texture->GetHandle());
glColor4fv(m_colour);

View File

@ -15,7 +15,7 @@
|
|
| Usage: The functions speak for themselves. Instantiate, then be
| sure to pass a loaded (using tex_load()) texture before
| sure to pass a loaded (using ogl_tex_load()) texture before
| calling Render().
|
| To do: TBA

View File

@ -56,7 +56,7 @@ CTextureEntry::~CTextureEntry()
m_LoadedTextures.erase(it);
if (m_Handle > 0)
tex_free(m_Handle);
ogl_tex_free(m_Handle);
for (GroupVector::iterator it=m_Groups.begin();it!=m_Groups.end();++it)
(*it)->RemoveTerrain(this);
@ -88,8 +88,7 @@ void CTextureEntry::BuildBaseColor()
return;
}
Handle handle=GetHandle();
g_Renderer.BindTexture(0,tex_id(handle));
ogl_tex_bind(GetHandle());
// get root colour for coloring minimap by querying root level of the texture
// (this should decompress any compressed textures for us),

View File

@ -4,6 +4,7 @@
#include "lib/ogl.h"
#include "lib/res/h_mgr.h"
#include "lib/res/graphics/tex.h"
#include "ps/CLogger.h"
#define LOG_CATEGORY "gui"
@ -16,7 +17,7 @@ void DrawCalls::clear()
for (iterator it = begin(); it != end(); ++it)
{
delete it->m_Effects;
tex_free(it->m_TexHandle);
ogl_tex_free(it->m_TexHandle);
}
std::vector<SDrawCall>::clear();
}
@ -123,7 +124,7 @@ public:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
tex_bind(tex);
ogl_tex_bind(tex);
}
void Unset()
@ -200,7 +201,7 @@ public:
glTexEnviv(GL_TEXTURE_ENV, GL_RGB_SCALE, TexScale4);
}
tex_bind(tex);
ogl_tex_bind(tex);
}
void Unset()
{
@ -267,7 +268,7 @@ public:
// Texture unit 0:
glEnable(GL_TEXTURE_2D);
tex_bind(tex);
ogl_tex_bind(tex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@ -289,7 +290,7 @@ public:
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
tex_bind(tex);
ogl_tex_bind(tex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@ -384,14 +385,14 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, CStr &SpriteName, CRect
if (cit->m_TextureName.Length())
{
Handle h = tex_load(cit->m_TextureName);
Handle h = ogl_tex_load(cit->m_TextureName);
if (h <= 0)
{
LOG(ERROR, LOG_CATEGORY, "Error reading texture '%s': %lld", (const char*)cit->m_TextureName, h);
return;
}
int err = tex_upload(h, GL_LINEAR);
int err = ogl_tex_upload(h, GL_LINEAR);
if (err < 0)
{
LOG(ERROR, LOG_CATEGORY, "Error uploading texture '%s': %d", (const char*)cit->m_TextureName, err);
@ -400,25 +401,13 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, CStr &SpriteName, CRect
Call.m_TexHandle = h;
int TexFormat, t_w, t_h;
tex_info(h, &t_w, &t_h, &TexFormat, NULL, NULL);
float TexWidth = (float)t_w, TexHeight = (float)t_h;
// TODO: Detect the presence of an alpha channel in a more precise way
// (particularly for no-alpha DXT1 textures)
switch (TexFormat)
{
case GL_RGBA:
case GL_BGRA:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
Call.m_EnableBlending = true;
break;
default:
Call.m_EnableBlending = false;
break;
}
int t_w = 0, t_h = 0;
(void)ogl_tex_get_size(h, &t_w, &t_h, 0);
float TexWidth = t_w, TexHeight = t_h;
int flags = 0; // assume no alpha on failure
(void)ogl_tex_get_format(h, &flags, 0);
Call.m_EnableBlending = (flags & TEX_ALPHA) != 0;
// Textures are positioned by defining a rectangular block of the
// texture (usually the whole texture), and a rectangular block on
@ -551,7 +540,7 @@ void GUIRenderer::Draw(DrawCalls &Calls)
{
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
tex_bind(cit->m_TexHandle);
ogl_tex_bind(cit->m_TexHandle);
}
glBegin(GL_QUADS);

View File

@ -8,8 +8,8 @@
#include "lib.h"
int tex_filter = GL_LINEAR;
uint tex_bpp = 32; // 16 or 32
GLint ogl_tex_filter = GL_LINEAR;
uint ogl_tex_bpp = 32; // 16 or 32
//////////////////////////////////////////////////////////////////////////////
@ -64,15 +64,15 @@ static bool filter_uses_mipmaps(GLint filter)
}
// determine OpenGL texture format, given <bpp> and TexInfo <flags>.
// also choose an internal format based on the global <tex_bpp>
// determine OpenGL texture format, given <bpp> and Tex <flags>.
// also choose an internal format based on the global <ogl_tex_bpp>
// performance vs. quality setting.
//
// rationale: we override the user's previous internal format preference.
// this is reasonable: 1) internal format is mostly performance optimization
// 2) if it does turn out to be significant, better to reevaluate the
// format decision after a reload than keep the user's setting.
static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLint* int_fmt)
{
const bool alpha = (flags & TEX_ALPHA) != 0;
const bool bgr = (flags & TEX_BGR ) != 0;
@ -111,7 +111,7 @@ static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
// true => 8 bits per component; otherwise, 4
const bool high_quality = (tex_bpp == 32);
const bool high_quality = (ogl_tex_bpp == 32);
switch(bpp)
{
@ -175,135 +175,174 @@ static GLint detect_auto_mipmap_gen()
//
//////////////////////////////////////////////////////////////////////////////
struct Tex
struct OglTex
{
TexInfo ti;
Tex t;
// allocated by Tex_reload; indicates the texture is currently uploaded.
GLuint id;
// determined from TexInfo by gl_get_fmt (called from Tex_reload);
// user settings passed to tex_upload will override this until the
// determined from Tex by gl_get_fmt (called from Tex_reload);
// user settings passed to ogl_tex_upload will override this until the
// next actual reload.
GLenum fmt;
GLenum int_fmt;
GLint int_fmt;
// set to default <tex_filter> by Tex_init; user settings passed to
// tex_upload will permanently override this.
// set to default <ogl_tex_filter> by Tex_init; user settings passed to
// ogl_tex_upload will permanently override this.
GLint filter;
// flags influencing reload behavior
bool is_loaded;
// either we have the texture in memory (referenced by ti.hm),
// either we have the texture in memory (referenced by t.hm),
// or it's already been uploaded to OpenGL => no reload necessary.
// needs to be a flag so it can be reset in Tex_dtor.
bool has_been_uploaded;
};
H_TYPE_DEFINE(Tex);
H_TYPE_DEFINE(OglTex);
static void Tex_init(Tex* t, va_list UNUSED(args))
static void OglTex_init(OglTex* ot, va_list UNUSED(args))
{
// set to default (once)
t->filter = tex_filter;
ot->filter = ogl_tex_filter;
}
static void Tex_dtor(Tex* t)
static void OglTex_dtor(OglTex* ot)
{
tex_free(&t->ti);
tex_free(&ot->t);
glDeleteTextures(1, &t->id);
t->id = 0;
glDeleteTextures(1, &ot->id);
ot->id = 0;
// need to clear this so actual reloads (triggered by h_reload)
// actually reload.
t->is_loaded = false;
ot->is_loaded = false;
}
static int Tex_reload(Tex* t, const char* fn, Handle h)
static int OglTex_reload(OglTex* ot, const char* fn, Handle h)
{
if(t->is_loaded)
if(ot->is_loaded)
return 0;
TexInfo* const ti = &t->ti;
CHECK_ERR(tex_load(fn, ti));
CHECK_ERR(get_gl_fmt(ti->bpp, ti->flags, &t->fmt, &t->int_fmt));
Tex* const t = &ot->t;
CHECK_ERR(tex_load(fn, t));
CHECK_ERR(get_gl_fmt(t->bpp, t->flags, &ot->fmt, &ot->int_fmt));
// always override previous settings, since format in
// texture file may have changed (e.g. 24 -> 32 bpp).
t->is_loaded = true;
ot->is_loaded = true;
glGenTextures(1, &t->id);
glGenTextures(1, &ot->id);
// re-upload if necessary
if(t->has_been_uploaded)
CHECK_ERR(tex_upload(h, t->filter, t->int_fmt));
if(ot->has_been_uploaded)
CHECK_ERR(ogl_tex_upload(h, ot->filter, ot->int_fmt));
return 0;
}
Handle tex_load(const char* fn, int scope)
Handle ogl_tex_load(const char* fn, int scope)
{
return h_alloc(H_Tex, fn, scope);
return h_alloc(H_OglTex, fn, scope);
}
int tex_free(Handle& ht)
int ogl_tex_free(Handle& ht)
{
return h_free(ht, H_Tex);
return h_free(ht, H_OglTex);
}
int tex_bind(const Handle h)
/*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BindTexture: bind a GL texture object to current active unit
void CRenderer::BindTexture(int unit,GLuint tex)
{
Tex* t = H_USER_DATA(h, Tex);
if(!t)
#if 0
glActiveTextureARB(GL_TEXTURE0+unit);
if (tex==m_ActiveTextures[unit]) return;
if (tex) {
glBindTexture(GL_TEXTURE_2D,tex);
if (!m_ActiveTextures[unit]) {
glEnable(GL_TEXTURE_2D);
}
} else if (m_ActiveTextures[unit]) {
glDisable(GL_TEXTURE_2D);
}
m_ActiveTextures[unit]=tex;
#endif
glActiveTextureARB(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D,tex);
if (tex) {
glEnable(GL_TEXTURE_2D);
} else {
glDisable(GL_TEXTURE_2D);
}
m_ActiveTextures[unit]=tex;
}
*/
int ogl_tex_bind(const Handle h, GLenum unit)
{
int id = 0;
// special case: avoid dereference and disable texturing directly.
if(h == 0)
goto disable_texturing;
{
OglTex* ot = H_USER_DATA(h, OglTex);
if(!ot)
{
glBindTexture(GL_TEXTURE_2D, 0);
return ERR_INVALID_HANDLE;
}
#ifndef NDEBUG
if(!t->id)
if(!ot->id)
{
debug_warn("tex_bind: Tex.id is not a valid texture");
debug_warn("ogl_tex_bind: OglTex.id is not a valid texture");
return -1;
}
#endif
id = ot->id;
}
glBindTexture(GL_TEXTURE_2D, t->id);
disable_texturing:
glActiveTextureARB(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D, id);
if(id)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
return 0;
}
int tex_id(const Handle h)
{
Tex* t = H_USER_DATA(h, Tex);
return t ? t->id : 0;
}
static int tex_validate(const uint line, const Tex* t)
static int ogl_tex_validate(const uint line, const OglTex* ot)
{
const char* msg = 0;
int err = -1;
// pointer to texture data
size_t tex_file_size;
void* tex_file = mem_get_ptr(t->ti.hm, &tex_file_size);
void* tex_file = mem_get_ptr(ot->t.hm, &tex_file_size);
if(!tex_file)
msg = "texture file not loaded";
// possible causes: texture file header is invalid,
// or file wasn't loaded completely.
if(t->ti.ofs > tex_file_size)
if(ot->t.ofs > tex_file_size)
msg = "offset to texture data exceeds file size";
// width, height
GLsizei w = (GLsizei)t->ti.w;
GLsizei h = (GLsizei)t->ti.h;
GLsizei w = (GLsizei)ot->t.w;
GLsizei h = (GLsizei)ot->t.h;
// if w or h is 0, texture file probably not loaded successfully.
if(w == 0 || h == 0)
msg = "width or height is 0 - texture probably not loaded successfully";
@ -318,7 +357,7 @@ static int tex_validate(const uint line, const Tex* t)
msg = "width or height is not a power-of-2";
// texel format
GLenum fmt = (GLenum)t->fmt;
GLenum fmt = (GLenum)ot->fmt;
if(!fmt)
msg = "texel format is 0";
// can't really check against a list of valid formats - loaders
@ -326,18 +365,18 @@ static int tex_validate(const uint line, const Tex* t)
// loader knows what it's doing, and that the format is valid.
// bits per pixel
u32 bpp = t->ti.bpp;
u32 bpp = ot->t.bpp;
// half-hearted sanity check: must be divisible by 4.
// don't bother checking all values.
if(bpp % 4 || bpp > 32)
msg = "invalid bpp? should be one of {4,8,16,24,32}";
// upload parameters, set by tex_upload(Handle), or 0
GLint filter = t->filter;
// upload parameters, set by ogl_tex_upload(Handle), or 0
GLint filter = ot->filter;
if(filter != 0 && !filter_is_known(filter))
msg = "invalid filter";
// as with the texel format above, there is not anything we can do
// to verify t->int_fmt is correct (even 0 is valid).
// to verify ot->int_fmt is correct (even 0 is valid).
if(msg)
{
@ -349,40 +388,40 @@ static int tex_validate(const uint line, const Tex* t)
return 0;
}
#define CHECK_TEX(t) CHECK_ERR(tex_validate(__LINE__, t))
#define CHECK_OGL_TEX(t) CHECK_ERR(ogl_tex_validate(__LINE__, t))
int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
int ogl_tex_upload(const Handle ht, GLint filter_ovr, GLint int_fmt_ovr, GLenum fmt_ovr)
{
H_DEREF(ht, Tex, t);
H_DEREF(ht, OglTex, ot);
// someone's requesting upload, but has already been uploaded.
// this happens if a cached texture is "loaded". no work to do.
if(t->id && t->ti.hm <= 0)
if(ot->id && ot->t.hm <= 0)
return 0;
CHECK_TEX(t); // must come after check above to avoid false alarms
CHECK_OGL_TEX(ot); // must come after check above to avoid false alarms
const char* fn = h_filename(ht);
if(!fn)
{
fn = "(could not determine filename)";
debug_warn("tex_upload(Handle): h_filename failed");
debug_warn("ogl_tex_upload(Handle): h_filename failed");
}
// allow user override of format/settings
if(filter_ovr) t->filter = filter_ovr;
if(int_fmt_ovr) t->int_fmt = int_fmt_ovr;
if(fmt_ovr) t->fmt = fmt_ovr;
if(filter_ovr) ot->filter = filter_ovr;
if(int_fmt_ovr) ot->int_fmt = int_fmt_ovr;
if(fmt_ovr) ot->fmt = fmt_ovr;
// convenient local copies. note: have been validated by CHECK_TEX.
GLsizei w = (GLsizei)t->ti.w;
GLsizei h = (GLsizei)t->ti.h;
u32 bpp = t->ti.bpp; // used for S3TC/mipmap size calc
GLenum fmt = t->fmt;
GLint filter = t->filter;
GLenum int_fmt = t->int_fmt;
void* tex_data = (u8*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
GLsizei w = (GLsizei)ot->t.w;
GLsizei h = (GLsizei)ot->t.h;
u32 bpp = ot->t.bpp; // used for S3TC/mipmap size calc
GLenum fmt = ot->fmt;
GLint filter = ot->filter;
GLint int_fmt = ot->int_fmt;
void* tex_data = tex_get_data(&ot->t);
// does filter call for uploading mipmaps?
const bool need_mipmaps = filter_uses_mipmaps(filter);
@ -390,9 +429,9 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
ONCE(auto_mipmap_gen = detect_auto_mipmap_gen());
CHECK_ERR(tex_bind(ht));
// we know ht is valid (H_DEREF above), but tex_bind can
// fail in debug builds if Tex.id isn't a valid texture name
CHECK_ERR(ogl_tex_bind(ht));
// we know ht is valid (H_DEREF above), but ogl_tex_bind can
// fail in debug builds if OglTex.id isn't a valid texture name
// set upload params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
@ -452,7 +491,7 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
*/
bool is_compressed = fmt_is_s3tc(fmt);
bool has_mipmaps = (t->ti.flags & TEX_MIPMAPS ? true : false);
bool has_mipmaps = (ot->t.flags & TEX_MIPMAPS ? true : false);
enum UploadState
{
@ -527,11 +566,11 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
}
}
else
debug_warn("Invalid state in tex_upload");
debug_warn("Invalid state in ogl_tex_upload");
mem_free_h(t->ti.hm);
mem_free_h(ot->t.hm);
t->has_been_uploaded = true;
ot->has_been_uploaded = true;
oglCheck();
@ -539,22 +578,33 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
}
int tex_info(Handle ht, int* w, int* h, int* fmt, int* bpp, void** p)
int ogl_tex_get_size(Handle ht, int* w, int* h, int* bpp)
{
H_DEREF(ht, Tex, t);
H_DEREF(ht, OglTex, ot);
if(w)
*w = t->ti.w;
*w = ot->t.w;
if(h)
*h = t->ti.h;
if(fmt)
*fmt = t->fmt;
*h = ot->t.h;
if(bpp)
*bpp = t->ti.bpp;
if(p)
*p = (u8*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
*bpp = ot->t.bpp;
return 0;
}
int ogl_tex_get_format(Handle ht, int* flags, GLenum* fmt)
{
H_DEREF(ht, OglTex, ot);
if(flags)
*flags = ot->t.flags;
if(fmt)
*fmt = ot->fmt;
return 0;
}
int ogl_tex_get_data(Handle ht, void** p)
{
H_DEREF(ht, OglTex, ot);
*p = tex_get_data(&ot->t);
return 0;
}

View File

@ -2,25 +2,27 @@
#define OGL_TEX_H__
#include "../handle.h"
#include "lib/ogl.h"
#include "lib/types.h"
// load and return a handle to the texture given in <fn>.
// supports RAW, BMP, JP2, PNG, TGA, DDS
extern Handle tex_load(const char* fn, int scope = 0);
extern Handle ogl_tex_load(const char* fn, int scope = 0);
extern int tex_bind(Handle ht);
extern int tex_id(Handle ht);
extern int ogl_tex_bind(Handle ht, GLenum unit = 0);
extern int tex_info(Handle ht, int* w, int* h, int *fmt, int *bpp, void** p);
extern int tex_filter; // GL values; default: GL_LINEAR
extern unsigned int tex_bpp; // 16 or 32; default: 32
extern GLint ogl_tex_filter; // GL values; default: GL_LINEAR
extern uint ogl_tex_bpp; // 16 or 32; default: 32
// upload the specified texture to OpenGL. Texture filter and internal format
// may be specified to override the global defaults.
// side effect: binds the texture to the currently active unit.
extern int tex_upload(Handle ht, int filter_override = 0, int internal_fmt_override = 0, int format_override = 0);
extern int ogl_tex_upload(Handle ht, GLint filter_override = 0, GLint internal_fmt_override = 0, GLenum format_override = 0);
extern int tex_free(Handle& ht);
extern int ogl_tex_free(Handle& ht);
extern int ogl_tex_get_size(Handle ht, int* w, int* h, int* bpp);
extern int ogl_tex_get_format(Handle ht, int* flags, GLenum* fmt);
extern int ogl_tex_get_data(Handle ht, void** p);
#endif // #ifndef OGL_TEX_H__

View File

@ -34,7 +34,7 @@
#include "ModelDef.h"
#include "ogl.h"
#include "lib/res/mem.h"
#include "lib/res/file/file.h"
#include "lib/res/graphics/tex.h"
#include "lib/res/graphics/ogl_tex.h"
#include "timer.h"
@ -1000,25 +1000,22 @@ bool CRenderer::LoadTexture(CTexture* texture,u32 wrapflags)
// to whether this is a valid handle or not
return h==errorhandle ? true : false;
} else {
h=tex_load(texture->GetName());
h=ogl_tex_load(texture->GetName());
if (h <= 0) {
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\"",(const char*) texture->GetName());
texture->SetHandle(errorhandle);
return false;
} else {
int tw,th;
tex_info(h, &tw, &th, NULL, NULL, NULL);
tw&=(tw-1);
th&=(th-1);
if (tw || th) {
int tw=0,th=0;
(void)ogl_tex_get_size(h, &tw, &th, 0);
if(!is_pow2(tw) || !is_pow2(th)) {
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
tex_free(h);
ogl_tex_free(h);
texture->SetHandle(errorhandle);
return false;
} else {
BindTexture(0,tex_id(h));
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
ogl_tex_bind(h);
ogl_tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
if (wrapflags) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
@ -1069,12 +1066,8 @@ void CRenderer::BindTexture(int unit,GLuint tex)
// SetTexture: set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
void CRenderer::SetTexture(int unit,CTexture* texture)
{
if (texture) {
Handle h=texture->GetHandle();
BindTexture(unit,tex_id(h));
} else {
BindTexture(unit,0);
}
Handle h = texture? texture->GetHandle() : 0;
ogl_tex_bind(h, unit);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1083,18 +1076,11 @@ void CRenderer::SetTexture(int unit,CTexture* texture)
bool CRenderer::IsTextureTransparent(CTexture* texture)
{
if (!texture) return false;
Handle h=texture->GetHandle();
if (h<=0) return false;
int fmt;
int bpp;
tex_info(h, NULL, NULL, &fmt, &bpp, NULL);
if (bpp==24 || fmt == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) {
return false;
}
return true;
int flags = 0; // assume no alpha on failure
(void)ogl_tex_get_format(h, &flags, 0);
return (flags & TEX_ALPHA) != 0;
}
@ -1109,61 +1095,74 @@ inline void CopyTriple(unsigned char* dst,const unsigned char* src)
///////////////////////////////////////////////////////////////////////////////////////////////////
// LoadAlphaMaps: load the 14 default alpha maps, pack them into one composite texture and
// calculate the coordinate of each alphamap within this packed texture .. need to add
// validation that all maps are the same size
// calculate the coordinate of each alphamap within this packed texture
int CRenderer::LoadAlphaMaps()
{
//
// load all textures and store Handle in array
//
Handle textures[NumAlphaMaps];
const char* fnames[CRenderer::NumAlphaMaps] = {
"art/textures/terrain/alphamaps/special/blendcircle.png",
"art/textures/terrain/alphamaps/special/blendlshape.png",
"art/textures/terrain/alphamaps/special/blendedge.png",
"art/textures/terrain/alphamaps/special/blendedgecorner.png",
"art/textures/terrain/alphamaps/special/blendedgetwocorners.png",
"art/textures/terrain/alphamaps/special/blendfourcorners.png",
"art/textures/terrain/alphamaps/special/blendtwooppositecorners.png",
"art/textures/terrain/alphamaps/special/blendlshapecorner.png",
"art/textures/terrain/alphamaps/special/blendtwocorners.png",
"art/textures/terrain/alphamaps/special/blendcorner.png",
"art/textures/terrain/alphamaps/special/blendtwoedges.png",
"art/textures/terrain/alphamaps/special/blendthreecorners.png",
"art/textures/terrain/alphamaps/special/blendushape.png",
"art/textures/terrain/alphamaps/special/blendbad.png"
PathPackage pp;
(void)pp_set_dir(&pp, "art/textures/terrain/alphamaps/special");
const char* fnames[NumAlphaMaps] = {
"blendcircle.png",
"blendlshape.png",
"blendedge.png",
"blendedgecorner.png",
"blendedgetwocorners.png",
"blendfourcorners.png",
"blendtwooppositecorners.png",
"blendlshapecorner.png",
"blendtwocorners.png",
"blendcorner.png",
"blendtwoedges.png",
"blendthreecorners.png",
"blendushape.png",
"blendbad.png"
};
int base = 0; // texture width/height (see below)
// for convenience, we require all alpha maps to be of the same BPP
// (avoids another ogl_tex_get_size call, and doesn't hurt)
int bpp = 0;
for(int i=0;i<NumAlphaMaps;i++)
{
(void)pp_append_file(&pp, fnames[i]);
textures[i] = ogl_tex_load(pp.path);
WARN_ERR(textures[i]);
int i;
for (i=0;i<NumAlphaMaps;i++) {
textures[i]=tex_load(fnames[i]);
if (textures[i] <= 0) {
throw textures[i]; // FIXTHROW
// get its size and make sure they are all equal.
// (the packing algo assumes this)
int this_width = 0, this_bpp = 0; // fail-safe
(void)ogl_tex_get_size(textures[i], &this_width, 0, &this_bpp);
// .. first iteration: establish size
if(i == 0)
{
base = this_width;
bpp = this_bpp;
}
// .. not first: make sure texture size matches
else if(base != this_width || bpp != this_bpp)
DISPLAY_ERROR(L"Alpha maps are not identically sized (including pixel depth)");
}
int base;
i=tex_info(textures[0], &base, NULL, NULL, NULL, NULL);
int size=(base+4)*NumAlphaMaps;
int texsize=RoundUpToPowerOf2(size);
unsigned char* data=new unsigned char[texsize*base*3];
//
// copy each alpha map (tile) into one buffer, arrayed horizontally.
//
int tile_w = 2+base+2; // 2 pixel border (avoids bilinear filtering artifacts)
int total_w = RoundUpToPowerOf2(tile_w * NumAlphaMaps);
int total_h = base; debug_assert(is_pow2(total_h));
u8* data=new u8[total_w*total_h*3];
// for each tile on row
for (i=0;i<NumAlphaMaps;i++) {
int bpp;
for(int i=0;i<NumAlphaMaps;i++)
{
// get src of copy
const u8* src;
tex_info(textures[i], NULL, NULL, NULL, &bpp, (void **)&src);
const u8* src = 0;
(void)ogl_tex_get_data(textures[i], (void**)&src);
int srcstep=bpp/8;
// get destination of copy
u8* dst=data+3*(i*(base+4));
u8* dst=data+3*(i*tile_w);
// for each row of image
for (int j=0;j<base;j++) {
@ -1186,30 +1185,27 @@ int CRenderer::LoadAlphaMaps()
dst+=3;
// advance write pointer for next row
dst+=3*(texsize-(base+4));
dst+=3*(total_w-tile_w);
}
m_AlphaMapCoords[i].u0=float(i*(base+4)+2)/float(texsize);
m_AlphaMapCoords[i].u1=float((i+1)*(base+4)-2)/float(texsize);
m_AlphaMapCoords[i].u0=float(i*tile_w+2)/float(total_w);
m_AlphaMapCoords[i].u1=float((i+1)*tile_w-2)/float(total_w);
m_AlphaMapCoords[i].v0=0.0f;
m_AlphaMapCoords[i].v1=1.0f;
}
for (i=0;i<NumAlphaMaps;i++)
tex_free(textures[i]);
ogl_tex_free(textures[i]);
// upload the composite texture
glGenTextures(1,(GLuint*) &m_CompositeAlphaMap);
BindTexture(0,m_CompositeAlphaMap);
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,texsize,base,0,GL_RGB,GL_UNSIGNED_BYTE,data);
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,total_w,total_h,0,GL_RGB,GL_UNSIGNED_BYTE,data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
// GL_CLAMP_TO_EDGE
oglSquelchError(GL_INVALID_ENUM);
oglSquelchError(GL_INVALID_ENUM); // GL_CLAMP_TO_EDGE
delete[] data;
return 0;