2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gltexture.cpp
|
|
|
|
** Low level OpenGL texture handling. These classes are also
|
|
|
|
** containers for the various translations a texture can have.
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2004-2005 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
|
|
|
|
** covered by the terms of the GNU Lesser General Public License as published
|
|
|
|
** by the Free Software Foundation; either version 2.1 of the License, or (at
|
|
|
|
** your option) any later version.
|
|
|
|
** 5. Full disclosure of the entire project's source code, except for third
|
|
|
|
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gl/system/gl_system.h"
|
|
|
|
#include "templates.h"
|
|
|
|
#include "m_crc32.h"
|
|
|
|
#include "c_cvars.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "v_palette.h"
|
|
|
|
|
2013-09-03 16:29:39 +00:00
|
|
|
#include "gl/system/gl_interface.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/system/gl_cvars.h"
|
|
|
|
#include "gl/renderer/gl_renderer.h"
|
|
|
|
#include "gl/textures/gl_material.h"
|
|
|
|
|
|
|
|
|
|
|
|
extern TexFilter_s TexFilter[];
|
|
|
|
extern int TexFormat[];
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Static texture data
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES];
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// STATIC - Gets the maximum size of hardware textures
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
int FHardwareTexture::GetTexDimension(int value)
|
|
|
|
{
|
|
|
|
if (value > gl.max_texturesize) return gl.max_texturesize;
|
2014-04-06 12:35:44 +00:00
|
|
|
return value;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2014-04-15 09:59:41 +00:00
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Quick'n dirty image rescaling.
|
|
|
|
//
|
|
|
|
// This will only be used when the source texture is larger than
|
|
|
|
// what the hardware can manage (extremely rare in Doom)
|
|
|
|
//
|
|
|
|
// Code taken from wxWidgets
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
struct BoxPrecalc
|
|
|
|
{
|
|
|
|
int boxStart;
|
|
|
|
int boxEnd;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ResampleBoxPrecalc(TArray<BoxPrecalc>& boxes, int oldDim)
|
|
|
|
{
|
|
|
|
int newDim = boxes.Size();
|
|
|
|
const double scale_factor_1 = double(oldDim) / newDim;
|
|
|
|
const int scale_factor_2 = (int)(scale_factor_1 / 2);
|
|
|
|
|
|
|
|
for (int dst = 0; dst < newDim; ++dst)
|
|
|
|
{
|
|
|
|
// Source pixel in the Y direction
|
|
|
|
const int src_p = int(dst * scale_factor_1);
|
|
|
|
|
|
|
|
BoxPrecalc& precalc = boxes[dst];
|
|
|
|
precalc.boxStart = clamp<int>(int(src_p - scale_factor_1 / 2.0 + 1), 0, oldDim - 1);
|
|
|
|
precalc.boxEnd = clamp<int>(MAX<int>(precalc.boxStart + 1, int(src_p + scale_factor_2)), 0, oldDim - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FHardwareTexture::Resize(int width, int height, unsigned char *src_data, unsigned char *dst_data)
|
|
|
|
{
|
|
|
|
|
|
|
|
// This function implements a simple pre-blur/box averaging method for
|
|
|
|
// downsampling that gives reasonably smooth results To scale the image
|
|
|
|
// down we will need to gather a grid of pixels of the size of the scale
|
|
|
|
// factor in each direction and then do an averaging of the pixels.
|
|
|
|
|
|
|
|
TArray<BoxPrecalc> vPrecalcs(height);
|
|
|
|
TArray<BoxPrecalc> hPrecalcs(width);
|
|
|
|
|
|
|
|
ResampleBoxPrecalc(vPrecalcs, texheight);
|
|
|
|
ResampleBoxPrecalc(hPrecalcs, texwidth);
|
|
|
|
|
|
|
|
int averaged_pixels, averaged_alpha, src_pixel_index;
|
|
|
|
double sum_r, sum_g, sum_b, sum_a;
|
|
|
|
|
|
|
|
for (int y = 0; y < height; y++) // Destination image - Y direction
|
|
|
|
{
|
|
|
|
// Source pixel in the Y direction
|
|
|
|
const BoxPrecalc& vPrecalc = vPrecalcs[y];
|
|
|
|
|
|
|
|
for (int x = 0; x < width; x++) // Destination image - X direction
|
|
|
|
{
|
|
|
|
// Source pixel in the X direction
|
|
|
|
const BoxPrecalc& hPrecalc = hPrecalcs[x];
|
|
|
|
|
|
|
|
// Box of pixels to average
|
|
|
|
averaged_pixels = 0;
|
|
|
|
averaged_alpha = 0;
|
|
|
|
sum_r = sum_g = sum_b = sum_a = 0.0;
|
|
|
|
|
|
|
|
for (int j = vPrecalc.boxStart; j <= vPrecalc.boxEnd; ++j)
|
|
|
|
{
|
|
|
|
for (int i = hPrecalc.boxStart; i <= hPrecalc.boxEnd; ++i)
|
|
|
|
{
|
|
|
|
// Calculate the actual index in our source pixels
|
|
|
|
src_pixel_index = j * texwidth + i;
|
|
|
|
|
|
|
|
int a = src_data[src_pixel_index * 4 + 3];
|
|
|
|
if (a > 0) // do not use color from fully transparent pixels
|
|
|
|
{
|
|
|
|
sum_r += src_data[src_pixel_index * 4 + 0];
|
|
|
|
sum_g += src_data[src_pixel_index * 4 + 1];
|
|
|
|
sum_b += src_data[src_pixel_index * 4 + 2];
|
|
|
|
sum_a += a;
|
|
|
|
averaged_pixels++;
|
|
|
|
}
|
|
|
|
averaged_alpha++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the average from the sum and number of averaged pixels
|
|
|
|
dst_data[0] = (unsigned char)xs_CRoundToInt(sum_r / averaged_pixels);
|
|
|
|
dst_data[1] = (unsigned char)xs_CRoundToInt(sum_g / averaged_pixels);
|
|
|
|
dst_data[2] = (unsigned char)xs_CRoundToInt(sum_b / averaged_pixels);
|
|
|
|
dst_data[3] = (unsigned char)xs_CRoundToInt(sum_a / averaged_alpha);
|
|
|
|
dst_data += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Loads the texture image into the hardware
|
|
|
|
//
|
|
|
|
// NOTE: For some strange reason I was unable to find the source buffer
|
|
|
|
// should be one line higher than the actual texture. I got extremely
|
|
|
|
// strange crashes deep inside the GL driver when I didn't do it!
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
void FHardwareTexture::LoadImage(unsigned char * buffer,int w, int h, unsigned int & glTexID,int wrapparam, bool alphatexture, int texunit)
|
|
|
|
{
|
|
|
|
int rh,rw;
|
|
|
|
int texformat=TexFormat[gl_texture_format];
|
|
|
|
bool deletebuffer=false;
|
|
|
|
bool use_mipmapping = TexFilter[gl_texture_filter].mipmapping;
|
|
|
|
|
2014-06-21 10:52:19 +00:00
|
|
|
if (alphatexture)
|
|
|
|
{
|
|
|
|
// thanks to deprecation and delayed introduction of a suitable replacement feature this has become a bit messy...
|
2014-07-30 21:13:16 +00:00
|
|
|
// Of all the targeted hardware, the Intel GMA 2000 and 3000 are the only ones not supporting texture swizzle, and they
|
|
|
|
// are also the only ones not supoorting GL 3.3. On those we are forced to use a full RGBA texture here.
|
2014-06-21 10:52:19 +00:00
|
|
|
if (gl.version >= 3.3f)
|
|
|
|
{
|
|
|
|
texformat = GL_R8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
texformat = GL_RGBA8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (forcenocompression)
|
|
|
|
{
|
|
|
|
texformat = GL_RGBA8;
|
|
|
|
}
|
2013-09-03 12:05:41 +00:00
|
|
|
if (glTexID==0) glGenTextures(1,&glTexID);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, glTexID);
|
2013-06-23 07:49:34 +00:00
|
|
|
lastbound[texunit]=glTexID;
|
|
|
|
|
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
w=texwidth;
|
|
|
|
h=abs(texheight);
|
|
|
|
rw = GetTexDimension (w);
|
|
|
|
rh = GetTexDimension (h);
|
|
|
|
|
|
|
|
// The texture must at least be initialized if no data is present.
|
|
|
|
mipmap=false;
|
|
|
|
buffer=(unsigned char *)calloc(4,rw * (rh+1));
|
|
|
|
deletebuffer=true;
|
|
|
|
//texheight=-h;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rw = GetTexDimension (w);
|
|
|
|
rh = GetTexDimension (h);
|
|
|
|
|
2014-04-06 12:35:44 +00:00
|
|
|
if (rw < w || rh < h)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-04-06 12:35:44 +00:00
|
|
|
// The texture is larger than what the hardware can handle so scale it down.
|
2013-06-23 07:49:34 +00:00
|
|
|
unsigned char * scaledbuffer=(unsigned char *)calloc(4,rw * (rh+1));
|
|
|
|
if (scaledbuffer)
|
|
|
|
{
|
2014-04-15 09:59:41 +00:00
|
|
|
Resize(rw, rh, buffer, scaledbuffer);
|
2013-06-23 07:49:34 +00:00
|
|
|
deletebuffer=true;
|
|
|
|
buffer=scaledbuffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (deletebuffer) free(buffer);
|
|
|
|
|
2014-06-21 14:41:45 +00:00
|
|
|
if (mipmap && use_mipmapping && !forcenofiltering) glGenerateMipmap(GL_TEXTURE_2D);
|
2014-06-21 10:52:19 +00:00
|
|
|
if (alphatexture && gl.version >= 3.3f)
|
|
|
|
{
|
|
|
|
static const GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_RED};
|
|
|
|
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
|
|
|
|
// When using separate samplers the stuff below is not needed.
|
|
|
|
// if (gl.flags & RFL_SAMPLER_OBJECTS) return;
|
|
|
|
|
2014-07-14 16:48:46 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapparam);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapparam);
|
|
|
|
clampmode = wrapparam==GL_CLAMP_TO_EDGE? GLT_CLAMPX|GLT_CLAMPY : 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (forcenofiltering)
|
|
|
|
{
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mipmap && use_mipmapping)
|
|
|
|
{
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
|
2013-06-23 07:49:34 +00:00
|
|
|
if (gl_texture_filter_anisotropic)
|
|
|
|
{
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2013-09-03 12:05:41 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Creates a texture
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
FHardwareTexture::FHardwareTexture(int _width, int _height, bool _mipmap, bool wrap, bool nofilter, bool nocompression)
|
|
|
|
{
|
|
|
|
forcenocompression = nocompression;
|
|
|
|
mipmap=_mipmap;
|
|
|
|
texwidth=_width;
|
|
|
|
texheight=_height;
|
|
|
|
|
2014-05-11 17:44:19 +00:00
|
|
|
glDefTexID = 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
clampmode=0;
|
|
|
|
glDepthID = 0;
|
|
|
|
forcenofiltering = nofilter;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Deletes a texture id and unbinds it from the texture units
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
void FHardwareTexture::DeleteTexture(unsigned int texid)
|
|
|
|
{
|
|
|
|
if (texid != 0)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_TEXTURES; i++)
|
|
|
|
{
|
|
|
|
if (lastbound[i] == texid)
|
|
|
|
{
|
|
|
|
lastbound[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
2013-09-03 12:05:41 +00:00
|
|
|
glDeleteTextures(1, &texid);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Frees all associated resources
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
void FHardwareTexture::Clean(bool all)
|
|
|
|
{
|
|
|
|
int cm_arraysize = CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size();
|
|
|
|
|
|
|
|
if (all)
|
|
|
|
{
|
2014-05-11 17:44:19 +00:00
|
|
|
DeleteTexture(glDefTexID);
|
|
|
|
glDefTexID = 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
for(unsigned int i=0;i<glTexID_Translated.Size();i++)
|
|
|
|
{
|
|
|
|
DeleteTexture(glTexID_Translated[i].glTexID);
|
|
|
|
}
|
|
|
|
glTexID_Translated.Clear();
|
2013-09-03 16:29:39 +00:00
|
|
|
if (glDepthID != 0) glDeleteRenderbuffers(1, &glDepthID);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Destroys the texture
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
FHardwareTexture::~FHardwareTexture()
|
|
|
|
{
|
|
|
|
Clean(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Gets a texture ID address and validates all required data
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
2014-05-11 17:44:19 +00:00
|
|
|
unsigned * FHardwareTexture::GetTexID(int translation)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
if (translation==0)
|
|
|
|
{
|
2014-05-11 17:44:19 +00:00
|
|
|
return &glDefTexID;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// normally there aren't more than very few different
|
|
|
|
// translations here so this isn't performance critical.
|
|
|
|
for(unsigned int i=0;i<glTexID_Translated.Size();i++)
|
|
|
|
{
|
2014-05-11 17:44:19 +00:00
|
|
|
if (glTexID_Translated[i].translation == translation)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
return &glTexID_Translated[i].glTexID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int add = glTexID_Translated.Reserve(1);
|
|
|
|
glTexID_Translated[add].translation=translation;
|
|
|
|
glTexID_Translated[add].glTexID=0;
|
|
|
|
return &glTexID_Translated[add].glTexID;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Binds this patch
|
|
|
|
//
|
|
|
|
//===========================================================================
|
2014-05-11 17:44:19 +00:00
|
|
|
unsigned int FHardwareTexture::Bind(int texunit, int translation, bool alphatexture)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-05-11 17:44:19 +00:00
|
|
|
if (alphatexture) translation = TRANS_Alpha;
|
|
|
|
unsigned int * pTexID=GetTexID(translation);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (*pTexID!=0)
|
|
|
|
{
|
|
|
|
if (lastbound[texunit]==*pTexID) return *pTexID;
|
|
|
|
lastbound[texunit]=*pTexID;
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit);
|
2013-09-03 12:05:41 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, *pTexID);
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0);
|
2013-06-23 07:49:34 +00:00
|
|
|
return *pTexID;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FHardwareTexture::Unbind(int texunit)
|
|
|
|
{
|
|
|
|
if (lastbound[texunit] != 0)
|
|
|
|
{
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit);
|
2013-09-03 12:05:41 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0);
|
2013-06-23 07:49:34 +00:00
|
|
|
lastbound[texunit] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FHardwareTexture::UnbindAll()
|
|
|
|
{
|
|
|
|
for(int texunit = 0; texunit < 16; texunit++)
|
|
|
|
{
|
|
|
|
Unbind(texunit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Creates a depth buffer for this texture
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
int FHardwareTexture::GetDepthBuffer()
|
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
if (glDepthID == 0)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
glGenRenderbuffers(1, &glDepthID);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, glDepthID);
|
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
|
|
|
|
GetTexDimension(texwidth), GetTexDimension(texheight));
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
return glDepthID;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Binds this texture's surfaces to the current framrbuffer
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void FHardwareTexture::BindToFrameBuffer()
|
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glDefTexID, 0);
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer());
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// (re-)creates the texture
|
|
|
|
//
|
|
|
|
//===========================================================================
|
2014-05-11 17:44:19 +00:00
|
|
|
unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, bool wrap, int texunit, int translation, bool alphatexture)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-05-11 17:44:19 +00:00
|
|
|
if (alphatexture) translation = TRANS_Alpha;
|
|
|
|
unsigned int * pTexID=GetTexID(translation);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit);
|
2014-07-14 16:48:46 +00:00
|
|
|
LoadImage(buffer, w, h, *pTexID, wrap? GL_REPEAT:GL_CLAMP_TO_EDGE, alphatexture, texunit);
|
2013-09-03 16:29:39 +00:00
|
|
|
if (texunit != 0) glActiveTexture(GL_TEXTURE0);
|
2013-06-23 07:49:34 +00:00
|
|
|
return *pTexID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|