bool GLRenderWindow::init() { checkGL(); // TODO: is this necessary? if (!format().rgba()) Log.error() << "No RGBA mode for OpenGl available." << std::endl; RenderWindow::init(); bool result = false; FB_TEXTURE_TARGET = GL_TEXTURE_2D; if(m_fmt.getPixelFormat() == PixelFormat::RGBF_96) { FB_INTERNAL_TEXTURE_FORMAT = GL_RGB; FB_TEXTURE_FORMAT = GL_RGB; FB_TEXTURE_DATATYPE = GL_FLOAT; result = true; } else { if(m_fmt.getPixelFormat() == PixelFormat::RGBA_32) { FB_INTERNAL_TEXTURE_FORMAT = GL_RGBA; FB_TEXTURE_FORMAT = GL_RGBA; FB_TEXTURE_DATATYPE = GL_UNSIGNED_BYTE; } result = true; } return result; }
void Framebuffer::bindDefault() { glBindFramebuffer(GL_FRAMEBUFFER, 0); checkGL(glBindFramebuffer) glViewport(0, 0, sDefaultWidth, sDefaultHeight); checkGL(glViewport) }
bool VertexBuffer::init(const VertexFormat& format, size_t count, BufferUsage usage) { m_format = format; m_usage = usage; m_count = count; glGenBuffers(1, &m_bufferID); m_context.setCurrentVertexBuffer(this); glBufferData(GL_ARRAY_BUFFER, m_count * m_format.size(), nullptr, convertToGL(m_usage)); if (!checkGL("Error during creation of vertex buffer of format %s", m_format.asString().c_str())) { m_context.setCurrentVertexBuffer(nullptr); return false; } if (RenderStats* stats = m_context.stats()) stats->addVertexBuffer(size()); return true; }
bool IndexBuffer::init(size_t count, IndexBufferType type, BufferUsage usage) { m_type = type; m_usage = usage; m_count = count; glGenBuffers(1, &m_bufferID); m_context.setCurrentIndexBuffer(this); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_count * typeSize(m_type), nullptr, convertToGL(m_usage)); if (!checkGL("Error during creation of index buffer of element size %u", (uint) typeSize(m_type))) { m_context.setCurrentIndexBuffer(nullptr); return false; } if (RenderStats* stats = m_context.stats()) stats->addIndexBuffer(size()); return true; }
void printShaderInfoLog(GLuint shader_index) { char log[2048]; int actualLength = 0; glGetShaderInfoLog(shader_index, sizeof(log), &actualLength, log); checkGL(); std::cerr << "Shader info log for GL index " << shader_index << std::endl << log << std::endl; }
void printProgramInfoLog(GLuint program) { char log[2048]; int actualLength = 0; glGetProgramInfoLog(program, sizeof(log), &actualLength, log); checkGL(); std::cerr << "Program info log for GL index " << program << std::endl << log << std::endl; }
void DefaultFramebuffer::apply() const { glBindFramebuffer(GL_FRAMEBUFFER, 0); #if WENDY_DEBUG checkGL("Error when applying default framebuffer"); #endif }
GLuint compileShader(GLuint shaderType, const char** source) { GLuint cs = glCreateShader(shaderType); checkGL(); glShaderSource(cs, 1, source, 0); checkGL(); glCompileShader(cs); checkGL(); int params = -1; glGetShaderiv(cs, GL_COMPILE_STATUS, ¶ms); checkGL(); if(params != GL_TRUE) { std::cerr << "ERROR: GL shader index " << cs << " did not compile" << std::endl; printShaderInfoLog(cs); return 0; } return cs; }
bool OcclusionQuery::init() { glGenQueries(1, &m_queryID); if (!checkGL("OpenGL error during creation of occlusion query object")) return false; return true; }
int checkGlProgramLink(GLuint program) { int params = -1; glGetProgramiv(program, GL_LINK_STATUS, ¶ms); checkGL(); if(params != GL_TRUE) { std::cerr << "ERROR: could not link shader program with GL index " << program << std::endl; printProgramInfoLog(program); return 0; } return 1; }
bool TextureFramebuffer::init() { glGenFramebuffers(1, &m_bufferID); #if WENDY_DEBUG if (!checkGL("Error during image framebuffer creation")) return false; #endif return true; }
void Framebuffer::detachTexture() { bind(); glFramebufferTexture2D(GL_FRAMEBUFFER, mTexture.get()->isDepth() ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); if(mTexture.get()->isDepth()) makeRenderbuffer(); checkGL(glFramebufferTexture2D) mTexture.reset(); }
OcclusionQuery::~OcclusionQuery() { if (m_active) logError("Occlusion query destroyed while active"); if (m_queryID) glDeleteQueries(1, &m_queryID); #if NORI_DEBUG checkGL("OpenGL error during occlusion query deletion"); #endif }
void VertexBuffer::discard() { m_context.setCurrentVertexBuffer(this); glBufferData(GL_ARRAY_BUFFER, m_count * m_format.size(), nullptr, convertToGL(m_usage)); #if WENDY_DEBUG checkGL("Error during vertex buffer discard"); #endif }
bool compile_shaders(const char* vertex_shader_path, const char* fragment_shader_path, GLint& shader_program, PreLinkCallback* cb) { char* vertex_shader_source = 0; if(readFile(vertex_shader_path, &vertex_shader_source) == -1) { return false; } char* fragment_shader_source = 0; if(readFile(fragment_shader_path, &fragment_shader_source) == -1) { return false; } GLuint vs = compileShader(GL_VERTEX_SHADER, vertex_shader_source); if(vs == 0) { return false; } GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragment_shader_source); if(fs == 0) { return false; } delete [] vertex_shader_source; delete [] fragment_shader_source; shader_program = glCreateProgram(); glAttachShader(shader_program, fs); checkGL(); glAttachShader(shader_program, vs); checkGL(); cb->preLinkCallback(shader_program); glLinkProgram(shader_program); checkGL(); if(checkGlProgramLink(shader_program) == 0) { return false; } return true; }
void Framebuffer::setSRGB(bool enabled) { if (m_sRGB == enabled) return; Framebuffer& previous = m_context.currentFramebuffer(); apply(); if (enabled) { glEnable(GL_FRAMEBUFFER_SRGB); checkGL("Failed to enable framebuffer sRGB encoding"); } else { glDisable(GL_FRAMEBUFFER_SRGB); checkGL("Failed to disable framebuffer sRGB encoding"); } m_sRGB = enabled; previous.apply(); }
bool OcclusionQuery::hasResultAvailable() const { if (m_active) return false; int available; glGetQueryObjectiv(m_queryID, GL_QUERY_RESULT_AVAILABLE, &available); #if NORI_DEBUG if (!checkGL("OpenGL error during occlusion query result availability check")) return false; #endif return available ? true : false; }
void Framebuffer::attachTexture(const std::shared_ptr<Texture>& texture) { bind(); #ifdef _WIN32 glDrawBuffer(GL_NONE); checkGL(glDrawBuffer) glReadBuffer(GL_NONE); checkGL(glReadBuffer) #endif if(texture.get()->isDepth() && mDepthRenderBufferID != 0) { glDeleteRenderbuffers(1, &mDepthRenderBufferID); checkGL(glDeleteRenderbuffers) mDepthRenderBufferID = 0; } glFramebufferTexture2D(GL_FRAMEBUFFER, texture.get()->isDepth() ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get()->getID(), 0); int error = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(error != GL_FRAMEBUFFER_COMPLETE) { printf("GL Framebuffer error: %i\n", error); } mTexture = texture; }
void OcclusionQuery::begin() { if (m_active) { logError("Cannot begin already active occlusion query"); return; } glBeginQuery(GL_SAMPLES_PASSED, m_queryID); m_active = true; #if NORI_DEBUG checkGL("OpenGL error during occlusion query begin"); #endif }
void OcclusionQuery::end() { if (!m_active) { logError("Cannot end non-active occlusion query"); return; } glEndQuery(GL_SAMPLES_PASSED); m_active = false; #if NORI_DEBUG checkGL("OpenGL error during occlusion query end"); #endif }
void IndexBuffer::copyTo(void* target, size_t targetCount, size_t start) { if (start + targetCount > m_count) { logError("Too many indices requested from index buffer"); return; } m_context.setCurrentIndexBuffer(this); const size_t size = typeSize(m_type); glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * size, targetCount * size, target); #if WENDY_DEBUG checkGL("Error during copy from index buffer"); #endif }
void IndexBuffer::copyFrom(const void* source, size_t sourceCount, size_t start) { if (start + sourceCount > m_count) { logError("Too many indices submitted to index buffer"); return; } m_context.setCurrentIndexBuffer(this); const size_t size = typeSize(m_type); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * size, sourceCount * size, source); #if WENDY_DEBUG checkGL("Error during copy to index buffer"); #endif }
void VertexBuffer::copyTo(void* target, size_t targetCount, size_t start) { if (start + targetCount > m_count) { logError("Too many vertices requested from vertex buffer"); return; } m_context.setCurrentVertexBuffer(this); const size_t size = m_format.size(); glGetBufferSubData(GL_ARRAY_BUFFER, start * size, targetCount * size, target); #if WENDY_DEBUG checkGL("Error during copy from vertex buffer"); #endif }
void VertexBuffer::copyFrom(const void* source, size_t sourceCount, size_t start) { if (start + sourceCount > m_count) { logError("Too many vertices submitted to vertex buffer"); return; } m_context.setCurrentVertexBuffer(this); const size_t size = m_format.size(); glBufferSubData(GL_ARRAY_BUFFER, start * size, sourceCount * size, source); #if WENDY_DEBUG checkGL("Error during copy to vertex buffer"); #endif }
uint OcclusionQuery::result() const { if (m_active) { logError("Cannot retrieve result of active occlusion query"); return 0; } uint result; glGetQueryObjectuiv(m_queryID, GL_QUERY_RESULT, &result); #if NORI_DEBUG if (!checkGL("OpenGL error during occlusion query result retrieval")) return 0; #endif return result; }
Ref<Image> Framebuffer::data() const { Ref<Image> image = Image::create(m_context.cache(), PixelFormat::RGB8, width(), height()); if (!image) return nullptr; Framebuffer& previous = m_context.currentFramebuffer(); apply(); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, image->width(), image->height(), GL_RGB, GL_UNSIGNED_BYTE, image->pixels()); previous.apply(); if (!checkGL("Error when reading framebuffer data")) return nullptr; return image; }
void TextureFramebuffer::apply() const { glBindFramebuffer(GL_FRAMEBUFFER, m_bufferID); GLenum enables[5]; GLsizei count = 0; for (size_t i = 0; i < sizeof(enables) / sizeof(enables[0]); i++) { Attachment attachment = (Attachment) i; if (m_textures[i] && isColorAttachment(attachment)) enables[count++] = convertToGL(attachment); } if (count) glDrawBuffers(count, enables); else glDrawBuffer(GL_NONE); #if WENDY_DEBUG checkGL("Error when applying image framebuffer"); #endif }
void printGLInfo() { std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl; checkGL(); std::cout << "OpenGL version supported: " << glGetString(GL_VERSION) << std::endl; checkGL(); }
void printAll(GLuint program) { std::cout << "*************** shader program " << program << " info ***************" << std::endl; int params = -1; glGetProgramiv(program, GL_LINK_STATUS, ¶ms); checkGL(); std::cout << "GL_LINK_STATUS: " << params << std::endl; glGetProgramiv(program, GL_ATTACHED_SHADERS, ¶ms); checkGL(); std::cout << "GL_ATTACHED_SHADERS: " << params << std::endl; glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, ¶ms); checkGL(); std::cout << "GL_ACTIVE_ATTRIBUTES: " << params << std::endl; int location = 0; char name[64]; char longName[64]; int actualLength = 0; int size = 0; GLenum type; for(int i = 0; i < params; ++i) { glGetActiveAttrib(program, i, sizeof(name), &actualLength, &size, &type, name); checkGL(); if(size > 1) { for(int j = 0; j < size; ++j) { sprintf(longName, "%s[%i]", name, j); location = glGetAttribLocation(program, longName); checkGL(); std::cout << " " << i << ") type: " << GLTypeToString(type) << " name: " << longName << " location: " << location << std::endl; } } else { location = glGetAttribLocation(program, name); checkGL(); std::cout << " " << i << ") type: " << GLTypeToString(type) << " name: " << name << " location: " << location << std::endl; } } glGetProgramiv(program, GL_ACTIVE_UNIFORMS, ¶ms); checkGL(); std::cout << "GL_ACTIVE_UNIFORMS: " << params << std::endl; for(int i = 0; i < params; ++i) { glGetActiveUniform(program, i, sizeof(name), &actualLength, &size, &type, name); checkGL(); if(size > 1) { for(int j = 0; j < size; ++j) { sprintf(longName, "%s[%i]", name, j); location = glGetUniformLocation(program, longName); checkGL(); std::cout << " " << i << ") type: " << GLTypeToString(type) << " name: " << longName << " location: " << location << std::endl; } } else { location = glGetUniformLocation(program, name); checkGL(); std::cout << " " << i << ") type: " << GLTypeToString(type) << " name: " << name << " location: " << location << std::endl; } } GLint blocks = 0; glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &blocks); checkGL(); std::cout << "GL_MAX_UNIFORM_BUFFER_BINDINGS = " << blocks << std::endl; printProgramInfoLog(program); }