Make use of (and require) OpenGL 4.x features present in mesa 11.0+
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
#version 330 core
|
||||
#extension GL_ARB_explicit_uniform_location : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
#ifdef GL_ARB_conservative_depth
|
||||
#extension GL_ARB_conservative_depth : enable
|
||||
#endif
|
||||
|
||||
layout(location = 2) uniform sampler2D texBase;
|
||||
layout(location = 3) uniform sampler2DArray texAnim;
|
||||
@@ -11,7 +14,9 @@ in vec2 fragTC;
|
||||
flat in uint fragUseAnimTex;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
#ifdef GL_ARB_conservative_depth
|
||||
layout(depth_unchanged) out float gl_FragDepth;
|
||||
#endif
|
||||
|
||||
void main(void) {
|
||||
vec4 texel = bool(fragUseAnimTex)?texture(texAnim, vec3(fragTC, animFrame)):texture(texBase, fragTC);
|
||||
@@ -44,7 +44,7 @@ namespace render {
|
||||
|
||||
/* Copy from paletted texture 'src' into BGRA texture 'dst' using palette 'palt'
|
||||
Palette entry 0xff is transparent, all others are opaque.
|
||||
For opaque pixels the color components are copied from a neighbouring
|
||||
For transparent pixels the color components are copied from a neighbouring
|
||||
opaque pixel if available.
|
||||
*/
|
||||
void copyPaletteTexture(uint8_t const* src, unsigned srcWidth, unsigned srcHeight,
|
||||
@@ -301,13 +301,13 @@ namespace render {
|
||||
atlasWidth*4,
|
||||
palt);
|
||||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlasWidth, atlasHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
|
||||
glTextureSubImage2D(tex, 0, 0, 0, atlasWidth, atlasHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
|
||||
auto mipdata = genMipmap(pixels.data(), atlasWidth, atlasHeight, minLg);
|
||||
size_t pos = 0;
|
||||
for (unsigned lvl = 1;lvl <= minLg;++lvl) {
|
||||
unsigned lWidth = std::max(atlasWidth>>lvl, 1u),
|
||||
lHeight = std::max(atlasHeight>>lvl, 1u);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, lvl, 0, 0, lWidth, lHeight,
|
||||
glTextureSubImage2D(tex, lvl, 0, 0, lWidth, lHeight,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos);
|
||||
pos += lWidth*lHeight*4;
|
||||
}
|
||||
@@ -344,7 +344,7 @@ namespace render {
|
||||
pixels.data()+f*width*height*4, width*4,
|
||||
palt);
|
||||
}
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, texAnim.frames,
|
||||
glTextureSubImage3D(tex, 0, 0, 0, 0, width, height, texAnim.frames,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
|
||||
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
||||
unsigned levels = std::max(logWidth, logHeight);
|
||||
@@ -355,7 +355,7 @@ namespace render {
|
||||
unsigned lWidth = std::max(width>>lvl, 1u),
|
||||
lHeight = std::max(height>>lvl, 1u);
|
||||
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, lvl, 0, 0, f, lWidth, lHeight, 1,
|
||||
glTextureSubImage3D(tex, lvl, 0, 0, f, lWidth, lHeight, 1,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos);
|
||||
pos += lWidth*lHeight*4;
|
||||
}
|
||||
@@ -481,14 +481,14 @@ namespace render {
|
||||
std::vector<TexAtlasInfo> atlasInfo;
|
||||
if (texs.size() > 0) {
|
||||
std::tie(atlasInfo, tex_) = genTexAtlas(texs, usedTexs, palt.getPalette());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR_MIPMAP_LINEAR));
|
||||
glTextureParameteri(tex_, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR_MIPMAP_LINEAR));
|
||||
}
|
||||
|
||||
auto& texAnims = obj.getTextureAnimations();
|
||||
AnimTexInfo animInfo;
|
||||
if ((usedTexs.find(atlasInfo.size()) != usedTexs.end()) && (texAnims.size() > 0)) {
|
||||
std::tie(animInfo, texAnim_) = genTexAnim(texAnims[0], palt.getPalette());
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR_MIPMAP_LINEAR));
|
||||
glTextureParameteri(texAnim_, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR_MIPMAP_LINEAR));
|
||||
}
|
||||
|
||||
// Generate vertex attribute array
|
||||
@@ -500,25 +500,26 @@ namespace render {
|
||||
std::tie(vertexAttribs, indices) = genVertexAttribs(obj, tris, quads, atlasInfo);
|
||||
|
||||
// Setup GL vertex buffer and vertex array
|
||||
glGenVertexArrays(1, &vertexArray_.get());
|
||||
glCreateVertexArrays(1, &vertexArray_.get());
|
||||
vbo_ = VBOManager::getInstance().alloc(sizeof(VertexAttribs)*vertexAttribs.size()+
|
||||
2*indices.size());
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
|
||||
glBindVertexArray(vertexArray_);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_.getVBOId());
|
||||
glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
|
||||
glVertexArrayElementBuffer(vertexArray_, vbo_.getVBOId());
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, sizeof(VertexAttribs),
|
||||
vbo_.getOfs(offsetof(VertexAttribs, vertex)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs),
|
||||
vbo_.getOfs(offsetof(VertexAttribs, texCoords)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribIPointer(2, 1, GL_UNSIGNED_BYTE, sizeof(VertexAttribs),
|
||||
vbo_.getOfs(offsetof(VertexAttribs, useTexAnim)));
|
||||
glEnableVertexArrayAttrib(vertexArray_, 0);
|
||||
glVertexArrayAttribFormat(vertexArray_, 0, 3, GL_INT, GL_FALSE, offsetof(VertexAttribs, vertex));
|
||||
glVertexArrayAttribBinding(vertexArray_, 0, 0);
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
|
||||
glEnableVertexArrayAttrib(vertexArray_, 1);
|
||||
glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords));
|
||||
glVertexArrayAttribBinding(vertexArray_, 1, 0);
|
||||
|
||||
glEnableVertexArrayAttrib(vertexArray_, 2);
|
||||
glVertexArrayAttribIFormat(vertexArray_, 2, 1, GL_UNSIGNED_BYTE, offsetof(VertexAttribs, useTexAnim));
|
||||
glVertexArrayAttribBinding(vertexArray_, 2, 0);
|
||||
|
||||
glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(),
|
||||
sizeof(VertexAttribs)*vertexAttribs.size(),
|
||||
vertexAttribs.data());
|
||||
|
||||
@@ -526,7 +527,7 @@ namespace render {
|
||||
indexOfs_ = sizeof(VertexAttribs)*vertexAttribs.size();
|
||||
numIndices_ = indices.size();
|
||||
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, vbo_.getBase()+indexOfs_,
|
||||
glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase()+indexOfs_,
|
||||
2*numIndices_,
|
||||
indices.data());
|
||||
|
||||
@@ -560,13 +561,13 @@ namespace render {
|
||||
glUniform1i(2, 0);
|
||||
glUniform1i(3, 1);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex_);
|
||||
if (texAnim_) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texAnim_);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1ui(4, animFrame_);
|
||||
}
|
||||
|
||||
std::array<GLuint, 2> texs{tex_, texAnim_};
|
||||
glBindTextures(0, 2, texs.data());
|
||||
} else
|
||||
glBindTextures(0, 1, &tex_.get());
|
||||
|
||||
glBindVertexArray(vertexArray_);
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace render {
|
||||
vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)),
|
||||
width_(width), height_(height), top_(top), left_(left), intWidth_(intWidth), intHeight_(intHeight)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_LINEAR));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_CLAMP_TO_EDGE));
|
||||
glTextureParameteri(texture_, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_NEAREST));
|
||||
glTextureParameteri(texture_, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE));
|
||||
glTextureParameteri(texture_, GL_TEXTURE_WRAP_T, static_cast<int>(GL_CLAMP_TO_EDGE));
|
||||
program_ = ProgramProvider::getInstance().getProgram("overlay", "overlay");
|
||||
|
||||
glGenVertexArrays(1, &vertexArray_.get());
|
||||
glCreateVertexArrays(1, &vertexArray_.get());
|
||||
short int t = top_, l = left_, b = height+top_, r = width+left_;
|
||||
std::vector<VertexAttribs> vertexAttribs{
|
||||
{{l, t}, {0, 0}},
|
||||
@@ -36,18 +36,16 @@ namespace render {
|
||||
{{l, b}, {0, 65535u}},
|
||||
{{r, b}, {65535u, 65535u}}};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
|
||||
glBindVertexArray(vertexArray_);
|
||||
glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, sizeof(VertexAttribs),
|
||||
vbo_.getOfs(offsetof(VertexAttribs, vertex)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs),
|
||||
vbo_.getOfs(offsetof(VertexAttribs, texCoords)));
|
||||
glEnableVertexArrayAttrib(vertexArray_, 0);
|
||||
glVertexArrayAttribFormat(vertexArray_, 0, 2, GL_SHORT, GL_FALSE, offsetof(VertexAttribs, vertex));
|
||||
glVertexArrayAttribBinding(vertexArray_, 0, 0);
|
||||
glEnableVertexArrayAttrib(vertexArray_, 1);
|
||||
glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords));
|
||||
glVertexArrayAttribBinding(vertexArray_, 1, 0);
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
|
||||
sizeof(VertexAttribs)*6,
|
||||
glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)*6,
|
||||
vertexAttribs.data());
|
||||
|
||||
ovlProj_ = glm::ortho(0.0f, static_cast<float>(renderer_.getWidth()),
|
||||
@@ -84,27 +82,23 @@ namespace render {
|
||||
(content->w > intWidth_))
|
||||
throw Exception{"null or mismatched surface"};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
|
||||
if (content->format->format != SDL_PIXELFORMAT_ARGB8888) {
|
||||
printf("Warning: Format conversion in Overlay::setContent\n");
|
||||
SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0));
|
||||
if (!tmpSurf)
|
||||
throw SDLException{};
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels);
|
||||
glTextureSubImage2D(texture_, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels);
|
||||
} else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels);
|
||||
glTextureSubImage2D(texture_, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels);
|
||||
}
|
||||
|
||||
void Overlay::setContentRGB8(void *data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
void Overlay::setContentBGRA8(void *data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ namespace render {
|
||||
ShaderResource vs(glCreateShader(GL_VERTEX_SHADER)),
|
||||
fs(glCreateShader(GL_FRAGMENT_SHADER));
|
||||
|
||||
shaderCompile_(vertexShader + ".vs", vs);
|
||||
shaderCompile_(fragShader + ".fs", fs);
|
||||
shaderCompile_(vertexShader + ".vert", vs);
|
||||
shaderCompile_(fragShader + ".frag", fs);
|
||||
|
||||
ProgramResource prog(glCreateProgram());
|
||||
glAttachShader(prog, vs);
|
||||
|
||||
@@ -56,13 +56,15 @@ namespace render {
|
||||
}
|
||||
|
||||
|
||||
void requireExtension(std::string const& extname) {
|
||||
bool support = SDL_GL_ExtensionSupported(extname.c_str());
|
||||
if (!support)
|
||||
throw Exception("Required OpenGL extension " + extname + " not found");
|
||||
}
|
||||
|
||||
Renderer::Renderer(bool fullscreen)
|
||||
: sdlInit_(), ttfInit_(), window_(), context_()
|
||||
{
|
||||
// Initialize OpenGL
|
||||
glbinding::Binding::initialize();
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
@@ -79,6 +81,9 @@ namespace render {
|
||||
|
||||
context_ = SDLGLContext(window_.get());
|
||||
|
||||
// Initialize OpenGL
|
||||
glbinding::Binding::initialize();
|
||||
|
||||
SDL_GetWindowSize(window_.get(), &width_, &height_);
|
||||
|
||||
glbinding::setCallbackMask(glbinding::CallbackMask::After);
|
||||
@@ -95,6 +100,14 @@ namespace render {
|
||||
}
|
||||
#endif
|
||||
|
||||
// All commercial GL implementations, and all mesa versions >= 11.0, should provide these
|
||||
requireExtension("GL_ARB_texture_storage");
|
||||
requireExtension("GL_ARB_buffer_storage");
|
||||
requireExtension("GL_ARB_direct_state_access");
|
||||
requireExtension("GL_ARB_shading_language_420pack");
|
||||
requireExtension("GL_ARB_explicit_uniform_location");
|
||||
requireExtension("GL_ARB_multi_bind");
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glViewport(0, 0, width_, height_);
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@ namespace render {
|
||||
{
|
||||
}
|
||||
|
||||
VBOManager::VBOAlloc VBOManager::alloc(size_t size, GLenum type)
|
||||
VBOManager::VBOAlloc VBOManager::alloc(size_t size)
|
||||
{
|
||||
for(auto& vbo : _vbos[type]) {
|
||||
for(auto& vbo : _vbos) {
|
||||
try {
|
||||
return vbo.alloc(size);
|
||||
} catch (AllocFailed &ex) {
|
||||
@@ -62,17 +62,17 @@ namespace render {
|
||||
}
|
||||
}
|
||||
|
||||
_vbos[type].emplace_back((size>default_size)?size:default_size, type);
|
||||
_vbos.emplace_back((size>default_size)?size:default_size);
|
||||
|
||||
return _vbos[type].back().alloc(size);
|
||||
return _vbos.back().alloc(size);
|
||||
}
|
||||
|
||||
VBOManager::VBO::VBO(size_t size, GLenum type)
|
||||
VBOManager::VBO::VBO(size_t size)
|
||||
: _bufID(0)
|
||||
{
|
||||
glGenBuffers(1, &_bufID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _bufID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, NULL, type);
|
||||
glCreateBuffers(1, &_bufID);
|
||||
glNamedBufferStorage(_bufID, size, NULL, GL_DYNAMIC_STORAGE_BIT);
|
||||
|
||||
_allocs.emplace_back(_Entry{size, false});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace render {
|
||||
|
||||
static const size_t default_size;
|
||||
static const size_t alignment = 4;
|
||||
static const gl::GLenum default_type = gl::GL_STATIC_DRAW;
|
||||
|
||||
class AllocFailed {};
|
||||
|
||||
@@ -72,13 +71,13 @@ namespace render {
|
||||
size_t _ofs, _size;
|
||||
};
|
||||
|
||||
VBOAlloc alloc(size_t size, gl::GLenum type = default_type);
|
||||
VBOAlloc alloc(size_t size);
|
||||
|
||||
private:
|
||||
|
||||
class VBO {
|
||||
public:
|
||||
VBO(size_t size = default_size, gl::GLenum type = default_type);
|
||||
VBO(size_t size = default_size);
|
||||
|
||||
VBO(VBO const& copy) = delete;
|
||||
VBO& operator=(VBO const& copy) = delete;
|
||||
@@ -108,7 +107,7 @@ namespace render {
|
||||
|
||||
};
|
||||
|
||||
std::map<gl::GLenum, std::vector<VBO> > _vbos;
|
||||
std::vector<VBO> _vbos;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -55,26 +55,16 @@ namespace render {
|
||||
TextureResource create2DTexture(unsigned width, unsigned height, bool alpha, unsigned levels)
|
||||
{
|
||||
TextureResource tex;
|
||||
glGenTextures(1, &tex.get());
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &tex.get());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
||||
|
||||
if (levels == 0)
|
||||
levels = std::max(logWidth,logHeight)+1u;
|
||||
|
||||
if(extensionSupported("GL_ARB_texture_storage"))
|
||||
glTexStorage2D(GL_TEXTURE_2D, levels, alpha?GL_RGBA8:GL_RGB8, width, height);
|
||||
else {
|
||||
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||
for (unsigned i = 0u; i < levels; ++i) {
|
||||
glTexImage2D(GL_TEXTURE_2D, i, static_cast<const int>(alpha?GL_RGBA8:GL_RGB8), width, height, 0,
|
||||
alpha?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
width = std::max(1u, (width / 2u));
|
||||
height = std::max(1u, (height / 2u));
|
||||
}
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels-1);
|
||||
glTextureStorage2D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height);
|
||||
|
||||
glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1);
|
||||
|
||||
return tex;
|
||||
}
|
||||
@@ -83,27 +73,16 @@ namespace render {
|
||||
bool alpha, unsigned levels)
|
||||
{
|
||||
TextureResource tex;
|
||||
glGenTextures(1, &tex.get());
|
||||
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &tex.get());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
||||
|
||||
if (levels == 0)
|
||||
levels = std::max(logWidth,logHeight)+1u;
|
||||
|
||||
if(extensionSupported("GL_ARB_texture_storage"))
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count);
|
||||
else {
|
||||
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||
for (unsigned i = 0u; i < levels; ++i) {
|
||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, i, static_cast<const int>(alpha?GL_RGBA8:GL_RGB8),
|
||||
width, height, count,
|
||||
0, alpha?GL_RGBA8:GL_RGB8, GL_UNSIGNED_BYTE, NULL);
|
||||
width = std::max(1u, (width / 2u));
|
||||
height = std::max(1u, (height / 2u));
|
||||
}
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, levels-1);
|
||||
glTextureStorage3D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count);
|
||||
|
||||
glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user