SpiderPig Posted September 1, 2018 Share Posted September 1, 2018 As well as trying out texture atlases I'm looking into textures arrays too, but am having trouble finding information on how to set it up. This is what I have so far; Material* mat = Material::Load("Materials\\terrain.mat"); Texture* texture = Texture::Load("Terrain\\beach_dirt_b.tex"); OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); int _width = texture->GetWidth(), _height = texture->GetHeight(); char* buf = new char[texture->GetMipmapSize(0) * 4]; texture->GetPixels(buf); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, _width, _height, 1); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 1, GL_RGBA8, GL_BYTE, buf); Part of the Fragment Shader; #version 430 layout (binding = 0) uniform sampler2DArray tex; //in main() outcolor = texture(tex, vec3(coords.x, coords.y, 0)); All I get is total blackness on the terrain. Wondering if any of you guys know how to implement this? If needed I can make a small test program and upload that. A link I used; https://ferransole.wordpress.com/2014/06/09/array-textures/ Quote Link to comment Share on other sites More sharing options...
Josh Posted September 1, 2018 Share Posted September 1, 2018 This is how I do it: glTexImage3D(this->gltarget, 0, internalformat, size.x, size.y, size.z, 0, externalformat, type, nullptr); glTexStorage3D requires OpenGL 4.2, so I don't use it. And this: glTexSubImage3D(this->gltarget, miplevel, 0, 0, 0, mipwidth, mipheight, mipdepth, externalformat, type, data); For external format GL_RGBA8 is not valid, and it doesn't even make sense because you have another parameter that indicates the data is GL_BYTE (you probably want GL_UNSIGNED_BYTE for that). Quote Specifies the format of the pixel data. The following symbolic values are accepted: GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_DEPTH_COMPONENT, and GL_STENCIL_INDEX. https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexSubImage3D.xhtml 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted September 1, 2018 Share Posted September 1, 2018 Also you can make a call to glGetError() after each OpenGL command to see if you made any mistakes. https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetError.xml 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 1, 2018 Author Share Posted September 1, 2018 Thanks. I tried this in a separate project and all I'm getting is a black cube. glGetError() returns 0 so all good there. I've uploaded the entire mat and texture file too. #include "App.h" using namespace Leadwerks; App::App() : window(NULL), context(NULL), world(NULL), camera(NULL) {} App::~App() { delete world; delete window; } float lookspeed = 0.1, looksmoothing = 0.5; Vec3 mousepos; bool wireframe = false; bool App::Start() { window = Leadwerks::Window::Create(); context = Context::Create(window); world = World::Create(); world->SetGravity(0, 0, 0); camera = Camera::Create(); camera->Move(0, 2, -4); Light* light = DirectionalLight::Create(); light->SetRotation(35, 35, 0); Model* box = Model::Box(); box->Move(0, 1, 0); Material* mat = Material::Load("Materials\\Test.mat"); box->SetMaterial(mat); Texture* texture = Texture::Load("Materials\\bluegrid.tex"); int _width = texture->GetWidth(); int _height = texture->GetHeight(); char* buf = new char[texture->GetMipmapSize(0) * 4]; texture->GetPixels(buf); OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GLenum error1 = glGetError(); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); GLenum error2 = glGetError(); Model* floor = Model::Box(); floor->SetShape(Shape::Box()); floor->SetPosition(5, 0, 0); floor->SetScale(30, 0.1, 30); mousepos = window->GetMousePosition(); window->SetMousePosition(context->GetWidth() / 2, context->GetHeight() / 2); return true; } bool App::Loop() { if (window->Closed() || window->KeyDown(Key::Escape)) return false; if (window->KeyHit(Key::F3) == true) { camera->GetDebugPhysicsMode() == true ? camera->SetDebugPhysicsMode(false) : camera->SetDebugPhysicsMode(true); } if (window->KeyHit(Key::F4) == true) { camera->GetDebugEntityBoxesMode() == true ? camera->SetDebugEntityBoxesMode(false) : camera->SetDebugEntityBoxesMode(true); } if (window->KeyHit(Key::F2) == true) { if (wireframe == true) { camera->SetDrawMode(0); wireframe = false; } else { camera->SetDrawMode(2); wireframe = true; } } float cx = Math::Round(context->GetWidth() / 2); float cy = Math::Round(context->GetHeight() / 2); Vec3 mpos = window->GetMousePosition(); window->SetMousePosition(cx, cy); mpos = mpos * looksmoothing + mousepos * (1 - looksmoothing); float dx = (mpos.x - cx) * lookspeed; float dy = (mpos.y - cy) * lookspeed; Vec3 camrot = camera->GetRotation(); camrot.x += dy; camrot.y += dx; camera->SetRotation(camrot); mousepos = mpos; float _time = Time::GetSpeed(); float camspeed = 0.2f * _time; if (window->KeyDown(Key::Shift) == true) { camspeed = camspeed * 5.0f; } if (window->KeyDown(Key::W) == true) { camera->Move(0, 0, camspeed); } else if (window->KeyDown(Key::S) == true) { camera->Move(0, 0, -camspeed); } if (window->KeyDown(Key::A) == true) { camera->Move(-camspeed, 0, 0); } else if (window->KeyDown(Key::D) == true) { camera->Move(camspeed, 0, 0); } if (window->KeyDown(Key::T) == true) { camera->Move(0, camspeed, 0); } else if (window->KeyDown(Key::G) == true) { camera->Move(0, -camspeed, 0); } Leadwerks::Time::Update(); world->Update(); world->Render(); context->Sync(); return true; } The texture is uncompressed and has no mipmaps. It might have to do with the way I'm binding it, maybe it can't find the right location in the shader? Test.zip Quote Link to comment Share on other sites More sharing options...
Josh Posted September 1, 2018 Share Posted September 1, 2018 The uniform texture0 might not be getting set to '0' because the engine does not recognize texture arrays. You would have to cast the shader to an OpenGLShader object, then you can retrieve the right uniform, then you can set it yourself using OpenGL commands. Make sure the shader is enabled before setting the uniform value. 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 2, 2018 Author Share Posted September 2, 2018 3 hours ago, Josh said: You would have to cast the shader to an OpenGLShader object, then you can retrieve the right uniform This part I've done and seems to work; OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); Uniform* uniform = shader->GetUniform("arrayMap"); Not too sure what commands there are that can bind to the uniform. Google has not been too helpful... Is this right? glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0 + uniform->index); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); There are no errors being thrown by any of these GL commands either. I can't help but think the uniform itself needs to be activated so that the 2D_ARRAY can be bound to it rather than "_buffer" Quote Link to comment Share on other sites More sharing options...
Josh Posted September 2, 2018 Share Posted September 2, 2018 You want glUniform1i: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 2, 2018 Author Share Posted September 2, 2018 I can see how it's supposed to work, but I can tell why it's not... ? Texture* texture = Texture::Load("Materials\\bluegrid.tex"); int _width = texture->GetWidth(); int _height = texture->GetHeight(); char* buf = new char[texture->GetMipmapSize(0) * 4]; texture->GetPixels(buf); OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); Uniform* uniform = shader->GetUniform("arrayMap"); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); glUniform1i(uniform->index, _buffer); uniform sampler2DArray arrayMap; //main outcolor *= texture(arrayMap,vec3(ex_texcoords0.x,ex_texcoords0.y,0)); _buffer is an unsigned int, but when I use glUnfiorm1ui() it throws an GL_INVAILD_VALUE error. buf is a SIGNED_BYTE array but passing it to the OpenGL commands you recommend GL_UNSIGNED_BYTE. The texture is uncompressed and has no mipmaps. uniform->index is 0. So the uniform is being found because uniform is not equal to NULL. As far as I can tell the arguments for glTexImage3D and glTexSubImage3D conform to what the wiki says. Nothing is throwing an error. Maybe there's something overwriting it later on as the program runs? Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted September 2, 2018 Author Share Posted September 2, 2018 Found this on how to do it, but still no success. http://gaarlicbread.com/post/gl_2d_array Quote Link to comment Share on other sites More sharing options...
Josh Posted September 3, 2018 Share Posted September 3, 2018 glUniform1i(uniform->index, _buffer); The uniform is a texture unit, not a texture! Set it to 0 or something, and then bind the texture to texture unit 0. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 3, 2018 Author Share Posted September 3, 2018 Thanks. But still nothing. OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); Uniform* uniform = shader->GetUniform("arrayMap"); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); glUniform1i(uniform->index, 0); Quote Link to comment Share on other sites More sharing options...
Josh Posted September 3, 2018 Share Posted September 3, 2018 Oh, I see you used GLSL 4.3, which allows you to specify the texture unit in the shader. So setting the uniform is redundant. i dont see anything wrong. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 3, 2018 Author Share Posted September 3, 2018 Ah okay. Yeah I tried 4.2 and 4.3 so I could use the layout parameter. It doesn't work with it or without it. I also tried just sending the image as a regular TEXTURE_2D but still no success. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted September 3, 2018 Author Share Posted September 3, 2018 It's a shame. I really wanted this for the terrain. Atlases are a bit finicky. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted September 3, 2018 Author Share Posted September 3, 2018 I googled "texture arrays are black" and found this... Quote Now, here is a very common mistake made by every beginner OpenGL programmer: Code: [View] ...gen and bind texture glTexImage2D(GL_TEXTURE_2D, level0... width, height... pixels) ...draw with that texture The result is all black, because this texture is incomplete. What is "complete"? It means a complex combination of the mipmap geometry, the mipmap image formats, the sampler filtering modes, and sampler wrap modes are all compatible and will make sense when the texture is sampled in a shader So it may need more mipmaps at least, or other information about how to use the image... Quote Link to comment Share on other sites More sharing options...
Josh Posted September 5, 2018 Share Posted September 5, 2018 You need to set the filter mode: if (filtermode == TEXTURE_SMOOTH) { if (hasmipmaps) { //if (trilinearfiltermode == true or target == TEXTURE_CUBEMAP)//textureLOD needs trilinear filter for linear filtering on Intel cards //{ glTexParameteri(gltarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//yes trilinear filter //} //else //{ // glTexParameteri(gltarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);//no trilinear filter //} glTexParameteri(gltarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //if (driver->maxanisotropy>1.0) //{ glTexParameterf(gltarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);// Math::Clamp(anisotropy, 1.0, driver->maxanisotropy)); //} } else { glTexParameteri(gltarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(gltarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 5, 2018 Author Share Posted September 5, 2018 Thanks, but still no joy. It's odd, I've been able to use GL commands to set a shader_storage_object before. But not textures... sampler_2D or arrays... Model* box = Model::Box(); box->Move(0, 1, 0); Material* mat = Material::Load("Materials\\Test.mat"); box->SetMaterial(mat); Texture* texture = Texture::Load("Materials\\bluegrid.tex"); int _width = texture->GetWidth(); int _height = texture->GetHeight(); char* buf = new char[texture->GetMipmapSize(0) * 4]; texture->GetPixels(buf); OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); GLenum e4 = glGetError(); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GLenum e5 = glGetError(); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); GLenum e7 = glGetError(); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLenum e8 = glGetError(); Quote Link to comment Share on other sites More sharing options...
Josh Posted September 5, 2018 Share Posted September 5, 2018 You are giving glTexSubImage3D a depth of zero. Shouldn't depth be one? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted September 5, 2018 Share Posted September 5, 2018 FYI, you can use this command: glCheckError() If an error occurs it will print it out and generate a Leadwerks error, but it only works in Debug mode. In Release mode it will ignore OpenGL errors. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 5, 2018 Author Share Posted September 5, 2018 15 minutes ago, Josh said: You are giving glTexSubImage3D a depth of zero. Shouldn't depth be one? Ah okay. I thought it was an index referring to the position in the array, 0 being the start. But that would probably be the zoffset? So I set depth to 1; glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf); But now glTexSubImage3D() throws this error every time; Exception thrown at 0x04BF5160 (nvoglv32.dll) in TestingGrounds.debug.exe: 0xC0000005: Access violation reading location 0x0CCF1000. I will google the error after work. 16 minutes ago, Josh said: glCheckError() Thanks. I'll use this one instead. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted September 6, 2018 Author Share Posted September 6, 2018 Okay I solved the crash; Changed this; texture->GetMipmapSize(0) * 4 To this; texture->GetMipmapSize(0) * 8 Curious as to why I need to multiple by 8 though... Is GetMipmapSize() in bytes? After fixing the crash the result was still black... I will conquer this... Quote Link to comment Share on other sites More sharing options...
Josh Posted September 6, 2018 Share Posted September 6, 2018 GetMipMapSize() is the data size, and does not need to be multiplied by anything. If the format isn't uncompressed RGBA then it would be less than 4 BPP. You have two possible sources of error. You don't really know what's stored in that char buffer. Why not just create a buffer of 255 values that is width * height * 4 in size, and see if you can make the texture white? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 6, 2018 Author Share Posted September 6, 2018 Thanks. I was getting the size of a compressed image for one of the tests, so that was one issue. But still having no success even with defining the pixels manually. int _width = 1024; int _height = 1024; unsigned char* buf = new unsigned char[_width * _height * 4]; int index = 0; for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { buf[index] = 255; buf[index + 1] = 255; buf[index + 2] = 255; buf[index + 3] = 255; index+=4; } } OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); Quote Link to comment Share on other sites More sharing options...
Josh Posted September 9, 2018 Share Posted September 9, 2018 I sent some code that may help. 1 Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted September 23, 2018 Author Share Posted September 23, 2018 Finally got it to work in a dedicated project, but not in my game. Here's the code that works; Model* box = Model::Box(); box->Move(0, 1, 0); Material* mat = Material::Load("Materials\\Test.mat"); box->SetMaterial(mat); Texture* texture = Texture::Load("Materials\\bluegrid.tex"); int _width = texture->GetWidth(); int _height = texture->GetHeight(); int sze = texture->GetMipmapSize(0); char* buf = new char[sze]; texture->GetPixels(buf); OpenGLShader* shader = (OpenGLShader*)mat->GetShader(); glUseProgram(shader->program); GLuint _buffer; glGenTextures(1, &_buffer); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, _buffer); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, _width, _height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, _width, _height, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); However the exact same code in my game project fails with an access violation at this line in assembly; 0371FCE9 movzx ebx,byte ptr [esi+2] I'm using the same material and shader as the testing project, and am setting things up the same and at the begging in the Start() function after setting up the window, context and camera. I'm wondering if it could be something setup wrong in the solution settings? Any ideas? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.