static void GenTexture( const SDL_Surface * surface, const TextureInfo & info, unsigned & id, bool & alpha, std::ostream & error) { // detect channels int internalformat, format; GetTextureFormat(surface, info, internalformat, format, alpha); // gen texture glGenTextures(1, &id); CheckForOpenGLErrors("Texture ID generation", error); // init texture glBindTexture(GL_TEXTURE_2D, id); SetSampler(info); glTexImage2D(GL_TEXTURE_2D, 0, internalformat, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels); CheckForOpenGLErrors("Texture creation", error); // If we support generatemipmap, go ahead and do it regardless of the info.mipmap setting. // In the GL3 renderer the sampler decides whether or not to do mip filtering, so we conservatively make mipmaps available for all textures. GenerateMipmap(GL_TEXTURE_2D); }
void FrameBufferObject::Begin(GraphicsState & glstate, std::ostream & error_output, float viewscale) { CheckForOpenGLErrors("before FBO begin", error_output); assert(inited); assert(framebuffer_object > 0); assert(!textures.empty()); glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object); CheckForOpenGLErrors("FBO bind to framebuffer", error_output); FrameBufferTexture * tex = textures.back(); if (tex->GetTarget() == FrameBufferTexture::CUBEMAP) { glFramebufferTexture2D(GL_FRAMEBUFFER, tex->GetAttachment(), tex->GetSide(), tex->GetId(), 0); CheckForOpenGLErrors("FBO cubemap side attachment", error_output); } assert(CheckStatus(error_output)); glstate.SetViewport(int(tex->GetW() * viewscale), int(tex->GetH() * viewscale)); CheckForOpenGLErrors("during FBO begin", error_output); }
void GraphicsGL2::DrawScenePassPost( const GraphicsConfigPass & pass, std::ostream & error_output) { assert(pass.draw.back() == "postprocess"); if (!pass.conditions.Satisfied(conditions)) return; shader_map_type::iterator si = shaders.find(pass.shader); if (si == shaders.end()) { ReportOnce(&pass, "Shader " + pass.shader + " couldn't be found", error_output); return; } postprocess.SetShader(&si->second); std::vector <TextureInterface*> input_textures; GetScenePassInputTextures(pass.inputs, input_textures); postprocess.SetTextures(glstate, input_textures, error_output); postprocess.SetColorMask(glstate, pass.write_color, pass.write_alpha); postprocess.SetDepthMode(glstate, DepthModeFromString(pass.depthtest), pass.write_depth); postprocess.SetBlendMode(glstate, BlendModeFromString(pass.blendmode)); render_output_map_type::iterator oi = render_outputs.find(pass.output); if (oi == render_outputs.end()) { ReportOnce(&pass, "Render output " + pass.output + " couldn't be found", error_output); return; } RenderOutput & output = oi->second; // setup camera, even though we don't use it directly for the post process // we want to have some info available std::string cameraname = pass.camera; camera_map_type::iterator ci = cameras.find(cameraname); if (ci == cameras.end()) { ReportOnce(&pass, "Camera " + cameraname + " couldn't be found", error_output); return; } postprocess.SetCamera(ci->second); output.Begin(glstate, error_output); CheckForOpenGLErrors("render output begin", error_output); postprocess.ClearOutput(glstate, pass.clear_color, pass.clear_depth); postprocess.Render(glstate, error_output); CheckForOpenGLErrors("render finish", error_output); output.End(glstate, error_output); CheckForOpenGLErrors("render output end", error_output); }
void GraphicsGL2::ChangeDisplay( const int width, const int height, std::ostream & error_output) { glstate.SetViewport(width, height); CheckForOpenGLErrors("ChangeDisplay", error_output); w = width; h = height; }
void FrameBufferObject::End(GraphicsState & glstate, std::ostream & error_output) { CheckForOpenGLErrors("start of FBO end", error_output); if (singlesample_framebuffer_object) { glstate.BindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_object); glstate.BindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesample_framebuffer_object->framebuffer_object); assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); CheckForOpenGLErrors("FBO end multisample binding", error_output); const int w = singlesample_framebuffer_object->GetWidth(); const int h = singlesample_framebuffer_object->GetHeight(); glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); CheckForOpenGLErrors("FBO end multisample blit", error_output); } CheckForOpenGLErrors("FBO multisample blit", error_output); // optionally rebuild mipmaps for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { if ((*i)->HasMipMap()) { glstate.BindTexture(0, (*i)->GetTarget(), (*i)->GetId()); glGenerateMipmap((*i)->GetTarget()); glstate.BindTexture(0, (*i)->GetTarget(), 0); } } CheckForOpenGLErrors("end of FBO end", error_output); }
void RenderInputScene::SetTextures( GraphicsState & glstate, const std::vector <TextureInterface*> & textures, std::ostream & error_output) { for (unsigned i = 0; i < textures.size(); i++) { if (textures[i]) { glstate.BindTexture(i, textures[i]->GetTarget(), textures[i]->GetId()); if (CheckForOpenGLErrors("RenderDrawlists extra texture bind", error_output)) { error_output << "this error occurred while binding texture " << i << " id=" << textures[i]->GetId() << std::endl; } } } }
void GraphicsGL2::BeginScene(std::ostream & error_output) { glstate.Disable(GL_TEXTURE_2D); glstate.Enable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glShadeModel(GL_SMOOTH); glClearColor(0,0,0,0); glClearDepth(1.0f); glstate.Enable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glstate.Disable(GL_LIGHTING); glstate.SetColor(0.5,0.5,0.5,1.0); glPolygonOffset(-1.0,-1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); CheckForOpenGLErrors("BeginScene", error_output); }
void GraphicsGL2::ChangeDisplay( const int width, const int height, std::ostream & error_output) { glViewport(0, 0, (GLint)width, (GLint)height); GLfloat ratio = (GLfloat)width / (GLfloat)height; Mat4 m; glMatrixMode(GL_PROJECTION); m.Perspective(45.0f, ratio, 0.1f, 100.0f); glLoadMatrixf(m.GetArray()); glMatrixMode(GL_MODELVIEW); m.LoadIdentity(); glLoadMatrixf(m.GetArray()); CheckForOpenGLErrors("ChangeDisplay", error_output); w = width; h = height; }
static void AttachCubeSide(int i, FrameBufferObject & reflection_fbo, std::ostream & error_output) { switch (i) { case 0: reflection_fbo.SetCubeSide(FrameBufferTexture::POSX); break; case 1: reflection_fbo.SetCubeSide(FrameBufferTexture::NEGX); break; case 2: reflection_fbo.SetCubeSide(FrameBufferTexture::POSY); break; case 3: reflection_fbo.SetCubeSide(FrameBufferTexture::NEGY); break; case 4: reflection_fbo.SetCubeSide(FrameBufferTexture::POSZ); break; case 5: reflection_fbo.SetCubeSide(FrameBufferTexture::NEGZ); break; default: error_output << "Reached odd spot while attaching cubemap side. How many sides are in a cube, anyway? " << i << "?" << std::endl; assert(0); break; }; CheckForOpenGLErrors("cubemap generation: FBO cube side attachment", error_output); }
bool Texture::LoadDDS(const std::string & path, const TextureInfo & info, std::ostream & error) { std::ifstream file(path.c_str(), std::ifstream::in | std::ifstream::binary); if (!file) return false; // test for dds magic value char magic[4]; file.read(magic, 4); if (!IsDDS(magic, 4)) return false; // get length of file: file.seekg (0, file.end); const unsigned long length = file.tellg(); file.seekg (0, file.beg); // read file into memory std::vector<char> data(length); file.read(&data[0], length); // load dds const char * texdata(0); unsigned long texlen(0); unsigned format(0), width(0), height(0), levels(0); if (!ReadDDS( (void*)&data[0], length, (const void*&)texdata, texlen, format, width, height, levels)) { return false; } // set properties m_w = width; m_h = height; m_scale = 1.0f; m_alpha = (format != GL_BGR); m_cube = false; // gl3 renderer expects srgb unsigned iformat = format; if (info.srgb) { if (format == GL_BGR) iformat = GL_SRGB8; else if (format == GL_BGRA) iformat = GL_SRGB8_ALPHA8; else if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; else if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; else if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) iformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; } // load texture assert(!m_id); glGenTextures(1, &m_id); CheckForOpenGLErrors("Texture ID generation", error); glBindTexture(GL_TEXTURE_2D, m_id); SetSampler(info, levels > 1); const char * idata = texdata; unsigned blocklen = 16 * texlen / (width * height); unsigned ilen = texlen; unsigned iw = width; unsigned ih = height; for (unsigned i = 0; i < levels; ++i) { if (format == GL_BGR || format == GL_BGRA) { // fixme: support compression here? ilen = iw * ih * blocklen / 16; glTexImage2D(GL_TEXTURE_2D, i, iformat, iw, ih, 0, format, GL_UNSIGNED_BYTE, idata); } else { ilen = std::max(1u, iw / 4) * std::max(1u, ih / 4) * blocklen; glCompressedTexImage2D(GL_TEXTURE_2D, i, iformat, iw, ih, 0, ilen, idata); } CheckForOpenGLErrors("Texture creation", error); idata += ilen; iw = std::max(1u, iw / 2); ih = std::max(1u, ih / 2); } // force mipmaps for GL3 if (levels == 1) GenerateMipmap(GL_TEXTURE_2D); return true; }
bool Texture::LoadCubeVerticalCross(const std::string & path, const TextureInfo & info, std::ostream & error) { SDL_Surface * surface = IMG_Load(path.c_str()); if (!surface) { error << "Error loading texture file: " + path << std::endl; error << IMG_GetError() << std::endl; return false; } unsigned id = 0; glGenTextures(1, &id); CheckForOpenGLErrors("Cubemap ID generation", error); glBindTexture(GL_TEXTURE_CUBE_MAP, id); glEnable(GL_TEXTURE_CUBE_MAP); // set sampler glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (info.mipmap) { glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); if (!glGenerateMipmap) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); } m_id = id; m_w = surface->w / 3; m_h = surface->h / 4; // upload texture unsigned bytespp = surface->format->BytesPerPixel; std::vector<unsigned char> cubeface(m_w * m_h * bytespp); for (int i = 0; i < 6; ++i) { // detect channels int format = GL_RGB; switch (bytespp) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; default: error << "Texture has unknown format: " + path << std::endl; return false; break; } int offsetx = 0; int offsety = 0; GLenum targetparam; if (i == 0) { targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; offsetx = 0; offsety = m_h; } else if (i == 1) { targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X; offsetx = m_w*2; offsety = m_h; } else if (i == 2) { targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; offsetx = m_w; offsety = m_h*2; } else if (i == 3) { targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; offsetx = m_w; offsety = 0; } else if (i == 4) { targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; offsetx = m_w; offsety = m_h*3; } else if (i == 5) { targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; offsetx = m_w; offsety = m_h; } else { error << "Texture has unknown format: " + path << std::endl; return false; } if (i == 4) //special case for negative z { for (unsigned yi = 0; yi < m_h; yi++) { for (unsigned xi = 0; xi < m_w; xi++) { for (unsigned ci = 0; ci < bytespp; ci++) { int idx1 = ((m_h - yi - 1) + offsety) * surface->w * bytespp + (m_w - xi - 1 + offsetx) * bytespp + ci; int idx2 = yi * m_w * bytespp + xi * bytespp + ci; cubeface[idx2] = ((unsigned char *)(surface->pixels))[idx1]; } } } } else { for (unsigned yi = 0; yi < m_h; yi++) { for (unsigned xi = 0; xi < m_w; xi++) { for (unsigned ci = 0; ci < bytespp; ci++) { int idx1 = (yi + offsety) * surface->w * bytespp + (xi + offsetx) * bytespp + ci; int idx2 = yi * m_w * bytespp + xi * bytespp + ci; cubeface[idx2] = ((unsigned char *)(surface->pixels))[idx1]; } } } } glTexImage2D(targetparam, 0, format, m_w, m_h, 0, format, GL_UNSIGNED_BYTE, &cubeface[0]); } if (info.mipmap) GenerateMipmap(GL_TEXTURE_CUBE_MAP); glDisable(GL_TEXTURE_CUBE_MAP); CheckForOpenGLErrors("Cubemap creation", error); SDL_FreeSurface(surface); return true; }
bool Texture::LoadCube(const std::string & path, const TextureInfo & info, std::ostream & error) { if (info.verticalcross) { return LoadCubeVerticalCross(path, info, error); } std::string cubefiles[6]; cubefiles[0] = path+"-xp.png"; cubefiles[1] = path+"-xn.png"; cubefiles[2] = path+"-yn.png"; cubefiles[3] = path+"-yp.png"; cubefiles[4] = path+"-zn.png"; cubefiles[5] = path+"-zp.png"; unsigned id = 0; glGenTextures(1, &id); CheckForOpenGLErrors("Cubemap texture ID generation", error); glBindTexture(GL_TEXTURE_CUBE_MAP, id); m_id = id; for (int i = 0; i < 6; ++i) { SDL_Surface * surface = IMG_Load(cubefiles[i].c_str()); if (!surface) { error << "Error loading texture file: " + path + " (" + cubefiles[i] + ")" << std::endl; error << IMG_GetError() << std::endl; return false; } // store dimensions if (i != 0 && ((m_w != (unsigned)surface->w) || (m_h != (unsigned)surface->h))) { error << "Cube map sides aren't equal sizes" << std::endl; return false; } m_w = surface->w; m_h = surface->h; // detect channels int format = GL_RGB; switch (surface->format->BytesPerPixel) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; default: error << "Texture has unknown format: " + path + " (" + cubefiles[i] + ")" << std::endl; return false; break; } // Create MipMapped Texture GLenum targetparam; if (i == 0) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; else if (i == 1) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X; else if (i == 2) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; else if (i == 3) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; else if (i == 4) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; else if (i == 5) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; else { error << "Iterated too far: " + path + " (" + cubefiles[i] + ")" << std::endl; assert(0); } glTexImage2D(targetparam, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels ); SDL_FreeSurface(surface); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glDisable(GL_TEXTURE_CUBE_MAP); CheckForOpenGLErrors("Cubemap creation", error); return true; }
bool Texture::Load(const std::string & path, const TextureInfo & info, std::ostream & error) { if (texid) { error << "Tried to double load texture " << path << std::endl; return false; } if (!info.data && path.empty()) { error << "Tried to load a texture with an empty name" << std::endl; return false; } if (!info.data && LoadDDS(path, info, error)) { return true; } if (info.cube) { return LoadCube(path, info, error); } SDL_Surface * surface = 0; if (info.data) { Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif surface = SDL_CreateRGBSurfaceFrom( info.data, info.width, info.height, info.bytespp * 8, info.width * info.bytespp, rmask, gmask, bmask, amask); } else { surface = IMG_Load(path.c_str()); } if (!surface) { error << "Error loading texture file: " << path << std::endl; error << IMG_GetError() << std::endl; return false; } const unsigned char * pixels = (const unsigned char *)surface->pixels; const unsigned bytespp = surface->format->BytesPerPixel; unsigned pitch = surface->pitch; unsigned w = surface->w; unsigned h = surface->h; // downsample if requested by application std::vector<unsigned char> pixelsd; unsigned wd = w; unsigned hd = h; if (info.maxsize == TextureInfo::SMALL) { if (w > 256) wd = w / 4; else if (w > 128) wd = w / 2; if (h > 256) hd = h / 4; else if (h > 128) hd = h / 2; } else if (info.maxsize == TextureInfo::MEDIUM) { if (w > 256) wd = w / 2; if (h > 256) hd = h / 2; } if (wd < w || hd < h) { pixelsd.resize(wd * hd * bytespp); SampleDownAvg( bytespp, w, h, pitch, pixels, wd, hd, wd * bytespp, &pixelsd[0]); pixels = &pixelsd[0]; pitch = wd * bytespp; w = wd; h = hd; } // store dimensions width = w; height = h; target = GL_TEXTURE_2D; // gen texture glGenTextures(1, &texid); CheckForOpenGLErrors("Texture ID generation", error); // setup texture glBindTexture(GL_TEXTURE_2D, texid); SetSampler(info); int internalformat, format; GetTextureFormat(surface, info, internalformat, format); // upload texture data glTexImage2D(GL_TEXTURE_2D, 0, internalformat, w, h, 0, format, GL_UNSIGNED_BYTE, pixels); CheckForOpenGLErrors("Texture creation", error); // If we support generatemipmap, go ahead and do it regardless of the info.mipmap setting. // In the GL3 renderer the sampler decides whether or not to do mip filtering, // so we conservatively make mipmaps available for all textures. if (GLC_ARB_framebuffer_object) glGenerateMipmap(GL_TEXTURE_2D); SDL_FreeSurface(surface); return true; }
void FrameBufferObject::Init( GraphicsState & glstate, const std::vector <FrameBufferTexture*> & newtextures, std::ostream & error_output, bool force_multisample_off) { CheckForOpenGLErrors("FBO init start", error_output); const bool verbose = false; if (inited) { if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl; DeInit(); CheckForOpenGLErrors("FBO deinit", error_output); } inited = true; // need at least some textures assert(!newtextures.empty()); textures = newtextures; width = -1; height = -1; std::vector <FrameBufferTexture*> color_textures; FrameBufferTexture * depth_texture = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { // ensure consistent sizes if (width == -1) width = (*i)->GetW(); if (height == -1) height = (*i)->GetH(); assert(width == int((*i)->GetW())); assert(height == int((*i)->GetH())); // separate textures by type if ((*i)->GetFormat() == FrameBufferTexture::DEPTH24) { // can't have more than one depth attachment assert(!depth_texture); depth_texture = *i; } else { color_textures.push_back(*i); } } if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl; if (verbose) error_output << "INFO: color textures: " << color_textures.size() << std::endl; if (verbose && depth_texture) error_output << "INFO: depth texture: 1" << std::endl; // can't have more than 4 color attachments assert(color_textures.size() < 5); // check for cubemaps for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++) { if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP) { if (verbose) error_output << "INFO: found cubemap" << std::endl; // can't have MRT with cubemaps assert(color_textures.size() == 1); // can't have multisample with cubemaps assert((*i)->GetMultiSample() == 0); // can't have depth texture with cubemaps assert(!depth_texture); } } // find what multisample value to use int multisample = 0; if (!color_textures.empty()) { multisample = -1; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { if (multisample == -1) multisample = (*i)->GetMultiSample(); // all must have the same multisample assert(multisample == (*i)->GetMultiSample()); } } if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl; if (force_multisample_off) multisample = 0; // either we have no multisample or multisample and no depth texture assert((multisample == 0) || ((multisample > 0) && depth_texture)); // initialize framebuffer object glGenFramebuffers(1, &framebuffer_object); if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl; CheckForOpenGLErrors("FBO generation", error_output); // bind framebuffer glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object); CheckForOpenGLErrors("FBO binding", error_output); if (!depth_texture) { // create depth render buffer if we're not using a depth texture glGenRenderbuffers(1, &depth_renderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer); if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl; CheckForOpenGLErrors("FBO renderbuffer generation", error_output); if (multisample > 0) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height); if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl; } else { glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); } CheckForOpenGLErrors("FBO renderbuffer initialization", error_output); // attach depth render buffer to the FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_renderbuffer); if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl; CheckForOpenGLErrors("FBO renderbuffer attachment", error_output); } if (multisample > 0) { // create/attach separate multisample color buffers for each color texture multisample_renderbuffers.resize(color_textures.size(), 0); for (size_t i = 0; i < color_textures.size(); i++) { glGenRenderbuffers(1, &multisample_renderbuffers[i]); glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffers[i]); glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, color_textures[i]->GetFormat(), width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, multisample_renderbuffers[i]); if (verbose) error_output << "INFO: generating separate multisample color buffer " << i << std::endl; CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output); } } else { // attach color textures to frame buffer object int count = 0; for (std::vector <FrameBufferTexture*>::iterator i = color_textures.begin(); i != color_textures.end(); i++, count++) { int attachment = GL_COLOR_ATTACHMENT0 + count; if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP) { // if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->GetId(), 0); if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, (*i)->GetTarget(), (*i)->GetId(), 0); if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl; } (*i)->SetAttachment(attachment); CheckForOpenGLErrors("FBO attachment", error_output); } if (depth_texture) { // attach depth texture to frame buffer object glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture->GetTarget(), depth_texture->GetId(), 0); depth_texture->SetAttachment(GL_DEPTH_ATTACHMENT); if (verbose) error_output << "INFO: attaching depth texture" << std::endl; CheckForOpenGLErrors("FBO attachment", error_output); } } GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE}; { int count = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++, count++) { buffers[count] = GL_COLOR_ATTACHMENT0 + count; } glDrawBuffers(count, buffers); glReadBuffer(buffers[0]); CheckForOpenGLErrors("FBO buffer mask set", error_output); } if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl; if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl; if (!CheckStatus(error_output)) { error_output << "Error initializing FBO:" << std::endl; int count = 0; for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++) { error_output << "\t" << count << ". " << TargetToString(FrameBufferTexture::Target((*i)->GetTarget())); error_output << ": " << FormatToString((*i)->GetFormat()) << std::endl; count++; } assert(0); } // explicitely unbind framebuffer object glstate.BindFramebuffer(GL_FRAMEBUFFER, 0); CheckForOpenGLErrors("FBO unbinding", error_output); // if multisampling is on, create another framebuffer object for the single sample version of these textures if (multisample > 0) { if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl; assert(!singlesample_framebuffer_object); singlesample_framebuffer_object = new FrameBufferObject(); singlesample_framebuffer_object->Init(glstate, newtextures, error_output, true); } }
void RenderInputPostprocess::Render(GraphicsState & glstate, std::ostream & error_output) { assert(shader); CheckForOpenGLErrors("postprocess begin", error_output); glstate.SetColorMask(writecolor, writealpha); glstate.SetDepthMask(writedepth); if (clearcolor && cleardepth) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else if (clearcolor) glClear(GL_COLOR_BUFFER_BIT); else if (cleardepth) glClear(GL_DEPTH_BUFFER_BIT); shader->Enable(); CheckForOpenGLErrors("postprocess shader enable", error_output); Mat4 projMatrix, viewMatrix; projMatrix.SetOrthographic(0, 1, 0, 1, -1, 1); viewMatrix.LoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadMatrixf(projMatrix.GetArray()); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(viewMatrix.GetArray()); glstate.SetColor(1,1,1,1); SetBlendMode(glstate); if (writedepth || depth_mode != GL_ALWAYS) glstate.Enable(GL_DEPTH_TEST); else glstate.Disable(GL_DEPTH_TEST); glDepthFunc( depth_mode ); glstate.Enable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); CheckForOpenGLErrors("postprocess flag set", error_output); float maxu = 1.f; float maxv = 1.f; int num_nonnull = 0; for (unsigned int i = 0; i < source_textures.size(); i++) { //std::cout << i << ": " << source_textures[i] << std::endl; glActiveTexture(GL_TEXTURE0+i); if (source_textures[i]) { source_textures[i]->Activate(); num_nonnull++; if (source_textures[i]->IsRect()) { maxu = source_textures[i]->GetW(); maxv = source_textures[i]->GetH(); } } } if (source_textures.size() && !num_nonnull) { error_output << "Out of the " << source_textures.size() << " input textures provided as inputs to this postprocess stage, zero are available. This stage will have no effect." << std::endl; return; } glActiveTexture(GL_TEXTURE0); CheckForOpenGLErrors("postprocess texture set", error_output); // build the frustum corners float ratio = w/h; std::vector <Vec3 > frustum_corners(4); frustum_corners[0].Set(-lod_far,-lod_far,-lod_far); //BL frustum_corners[1].Set(lod_far,-lod_far,-lod_far); //BR frustum_corners[2].Set(lod_far,lod_far,-lod_far); //TR frustum_corners[3].Set(-lod_far,lod_far,-lod_far); //TL Mat4 inv_proj; inv_proj.InvPerspective(camfov, ratio, 0.1, lod_far); for (int i = 0; i < 4; i++) { inv_proj.TransformVectorOut(frustum_corners[i][0], frustum_corners[i][1], frustum_corners[i][2]); frustum_corners[i][2] = -lod_far; } // frustum corners in world space for dynamic sky shader std::vector <Vec3 > frustum_corners_w(4); Mat4 inv_view_rot; (-cam_rotation).GetMatrix4(inv_view_rot); for (int i = 0; i < 4; i++) { frustum_corners_w[i] = frustum_corners[i]; inv_view_rot.TransformVectorOut(frustum_corners_w[i][0], frustum_corners_w[i][1], frustum_corners_w[i][2]); } // send shader parameters { Vec3 lightvec = lightposition; cam_rotation.RotateVector(lightvec); shader->UploadActiveShaderParameter3f("directlight_eyespace_direction", lightvec); shader->UploadActiveShaderParameter1f("contrast", contrast); shader->UploadActiveShaderParameter1f("znear", 0.1); //std::cout << lightvec << std::endl; shader->UploadActiveShaderParameter3f("frustum_corner_bl", frustum_corners[0]); shader->UploadActiveShaderParameter3f("frustum_corner_br_delta", frustum_corners[1]-frustum_corners[0]); shader->UploadActiveShaderParameter3f("frustum_corner_tl_delta", frustum_corners[3]-frustum_corners[0]); } // draw a quad unsigned faces[2 * 3] = { 0, 1, 2, 2, 3, 0, }; float pos[4 * 3] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; // send the UV corners in UV set 0 float tc0[4 * 2] = { 0.0f, 0.0f, maxu, 0.0f, maxu, maxv, 0.0f, maxv, }; // send the frustum corners in UV set 1 float tc1[4 * 3] = { frustum_corners[0][0], frustum_corners[0][1], frustum_corners[0][2], frustum_corners[1][0], frustum_corners[1][1], frustum_corners[1][2], frustum_corners[2][0], frustum_corners[2][1], frustum_corners[2][2], frustum_corners[3][0], frustum_corners[3][1], frustum_corners[3][2], }; // fructum corners in world space in uv set 2 float tc2[4 * 3] = { frustum_corners_w[0][0], frustum_corners_w[0][1], frustum_corners_w[0][2], frustum_corners_w[1][0], frustum_corners_w[1][1], frustum_corners_w[1][2], frustum_corners_w[2][0], frustum_corners_w[2][1], frustum_corners_w[2][2], frustum_corners_w[3][0], frustum_corners_w[3][1], frustum_corners_w[3][2], }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, pos); glClientActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, tc0); glClientActiveTexture(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, tc1); glClientActiveTexture(GL_TEXTURE2); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, tc2); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, faces); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); CheckForOpenGLErrors("postprocess draw", error_output); glstate.Enable(GL_DEPTH_TEST); glstate.Disable(GL_TEXTURE_2D); for (unsigned int i = 0; i < source_textures.size(); i++) { //std::cout << i << ": " << source_textures[i] << std::endl; glActiveTexture(GL_TEXTURE0+i); if (source_textures[i]) source_textures[i]->Deactivate(); } glActiveTexture(GL_TEXTURE0); CheckForOpenGLErrors("postprocess end", error_output); }
void RenderManager::doRendering(void) { auto frameTime = omp_get_wtime(); glm::mat4 viewMatrix = X39::Singletons::Camera::getInstance().recalculateViewPort(); ::glm::vec4 vec = ::glm::vec4(0.0f); float pitch = (float)::X39::Singletons::Camera::getInstance().getPitch(); float yaw = (float)::X39::Singletons::Camera::getInstance().getYaw(); float modificator = 0.1F; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_LShift)) modificator = 1; if (::X39::Singletons::Mouse::getInstance().getMode() == ::X39::Singletons::Mouse::MouseMode::Camera) { if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_W)) vec.z -= 1 * modificator; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_A)) vec.x -= 1 * modificator; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_S)) vec.z += 1 * modificator; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_D)) vec.x += 1 * modificator; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_Spacebar)) vec.y += 1 * modificator; if (::X39::Singletons::KeyHandler::getInstance().isKeyPressed(::EngineKeySet::KEY_LCTRL)) vec.y -= 1 * modificator; } vec = viewMatrix * vec; ::X39::Singletons::Camera::getInstance().addPos(::glm::vec3(vec.x, vec.y, vec.z)); #pragma endregion glClearColor(0.25, 0.25, 0.25, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glShadeModel(GL_SMOOTH); glEnable(GL_TEXTURE_COORD_ARRAY); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_BLEND); glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); //http://wiki.delphigl.com/index.php/glBlendFunc for different examples glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glPushMatrix(); ::X39::Singletons::MaterialManager::getInstance().loadMaterial(::X39::Singletons::MaterialManager::getInstance().getMaterialByIndex(0)); for (auto& it : this->_entityList) { it->doRender(); } glPopMatrix(); //2D projection glPushMatrix(); glLoadIdentity(); glLoadIdentity(); glDisable(GL_CULL_FACE); glClear(GL_DEPTH_BUFFER_BIT); glm::vec3 camPos = ::X39::Singletons::Camera::getInstance().getPos(); char s[256]; sprintf(s, "POS: %lf, %lf, %lf\nPITCH: %lf, YAW: %lf, ROLL %lf", camPos.x, camPos.y, camPos.z, ::X39::Singletons::Camera::getInstance().getPitch(), ::X39::Singletons::Camera::getInstance().getYaw(), ::X39::Singletons::Camera::getInstance().getRoll()); ::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), s, 1.5, 0, 0); //char s[256]; frameTime = omp_get_wtime() - frameTime; sprintf(s, "FPS: %i", (int)(1 / frameTime)); ::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), s, 1.5, 0, 500); //::X39::GUI::GuiBase::drawText2D(::X39::Singletons::FontManager::getInstance().getFont(0), "abcdefghijklm\nnopqrstuvwxyz\nABCDEFGHIJKLM\nNOPQRSTUVWXYZ\n1234567890", 10, 0, 0); //::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'A', 0, 0, 200, 200); //::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'B', 200, 0, 200, 200); //::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'C', 200, 200, 200, 200); //::X39::GUI::GuiBase::drawChar2D(::X39::Singletons::FontManager::getInstance().getFont(0), 'D', 0, 200, 200, 200); //::X39::Singletons::FontManager::getInstance().fontShader.use(); //::X39::GUI::GuiBase::drawTexture2D( // ::X39::Singletons::FontManager::getInstance().getFont(0)->material, // ::X39::Singletons::FontManager::getInstance().getCharTextureIndex(::X39::Singletons::FontManager::getInstance().getFont(0), 'A'), // 0, 0, 16, 16, // 0, 0, 256, 256, // ::X39::Singletons::FontManager::getInstance().fontShader //); //::X39::Singletons::FontManager::getInstance().fontShader.unuse(); if (::X39::GlobalObject::getInstance().mainDisplay) ::X39::GlobalObject::getInstance().mainDisplay->draw(); glPopMatrix(); SwapBuffers(::X39::GlobalObject::getInstance().handleDeviceContext); CheckForOpenGLErrors(); }
void GraphicsGL2::EndScene(std::ostream & error_output) { CheckForOpenGLErrors("EndScene", error_output); }
bool GraphicsGL2::EnableShaders(std::ostream & info_output, std::ostream & error_output) { CheckForOpenGLErrors("EnableShaders: start", error_output); // unload shaders glUseProgramObjectARB(0); shaders.clear(); CheckForOpenGLErrors("EnableShaders: shader unload", error_output); // unload inputs/outputs render_outputs.clear(); texture_outputs.clear(); texture_inputs.clear(); CheckForOpenGLErrors("EnableShaders: FBO deinit", error_output); // reload configuration config = GraphicsConfig(); std::string rcpath = shaderpath + "/" + renderconfigfile; if (!config.Load(rcpath, error_output)) { error_output << "EnableShaders: Error loading render configuration file: " << rcpath << std::endl; return false; } bool ssao = (lighting > 0); bool ssao_low = (lighting == 1); bool ssao_high = (lighting == 2); bool reflection_disabled = (reflection_status == REFLECTION_DISABLED); bool reflection_dynamic = (reflection_status == REFLECTION_DYNAMIC); bool shadows_near = shadows; bool shadows_medium = shadows && shadow_distance > 0; bool shadows_far = shadows && shadow_distance > 1; bool shadow_quality_low = shadows && (shadow_quality == 0); bool shadow_quality_medium = shadows && (shadow_quality == 1); bool shadow_quality_high = shadows && (shadow_quality == 2); bool shadow_quality_vhigh = shadows && (shadow_quality == 3); bool shadow_quality_ultra = shadows && (shadow_quality == 4); // for now, map vhigh and ultra to high shadow_quality_high = shadow_quality_high || shadow_quality_vhigh || shadow_quality_ultra; shadow_quality_vhigh = false; shadow_quality_ultra = true; conditions.clear(); if (fsaa > 1) conditions.insert("fsaa"); #define ADDCONDITION(x) if (x) conditions.insert(#x) ADDCONDITION(bloom); ADDCONDITION(normalmaps); ADDCONDITION(ssao); ADDCONDITION(ssao_low); ADDCONDITION(ssao_high); ADDCONDITION(reflection_disabled); ADDCONDITION(reflection_dynamic); ADDCONDITION(shadows_near); ADDCONDITION(shadows_medium); ADDCONDITION(shadows_far); ADDCONDITION(shadow_quality_low); ADDCONDITION(shadow_quality_medium); ADDCONDITION(shadow_quality_high); ADDCONDITION(shadow_quality_vhigh); // ADDCONDITION(shadow_quality_ultra); ADDCONDITION(sky_dynamic); #undef ADDCONDITION // add some common textures if (reflection_status == REFLECTION_STATIC) texture_inputs["reflection_cube"] = static_reflection; texture_inputs["ambient_cube"] = static_ambient; // setup frame buffer textures const bool has_texture_float = GLEW_ARB_texture_float && GLEW_ARB_half_float_pixel; for (std::vector <GraphicsConfigOutput>::const_iterator i = config.outputs.begin(); i != config.outputs.end(); i++) { if (!i->conditions.Satisfied(conditions)) continue; if (texture_outputs.find(i->name) != texture_outputs.end()) { error_output << "Ignore duplicate definiion of output: " << i->name << std::endl; continue; } if (i->type == "framebuffer") { render_outputs[i->name].RenderToFramebuffer(w, h); } else { FrameBufferTexture::Target target = TextureTargetFromString(i->type); FrameBufferTexture::Format format = TextureFormatFromString(i->format); if (!has_texture_float && (format == FrameBufferTexture::RGBA16 || format == FrameBufferTexture::RGB16)) { error_output << "Your video card doesn't support floating point textures." << std::endl; error_output << "Failed to load render output: " << i->name << " " << i->type << std::endl; return false; } // initialize fbtexture int multisampling = (i->multisample < 0) ? fsaa : 0; FrameBufferTexture & fbtex = texture_outputs[i->name]; fbtex.Init( i->width.GetSize(w), i->height.GetSize(h), target, format, (i->filter == "nearest"), i->mipmap, error_output, multisampling, (i->format == "depthshadow")); // register texture as input texture_inputs[i->name] = fbtex; } info_output << "Initialized render output: " << i->name; info_output << (i->type != "framebuffer" ? " (FBO)" : " (framebuffer alias)") << std::endl; } render_outputs["framebuffer"].RenderToFramebuffer(w, h); // gen graphics config shaders map typedef std::map <std::string, const GraphicsConfigShader *> ConfigShaderMap; ConfigShaderMap config_shaders; for (std::vector <GraphicsConfigShader>::const_iterator s = config.shaders.begin(); s != config.shaders.end(); s++) { std::pair <ConfigShaderMap::iterator, bool> result = config_shaders.insert(std::make_pair(s->name, &*s)); if (!result.second) error_output << "Ignore duplicate definition of shader: " << s->name << std::endl; } // setup frame buffer objects and shaders std::vector <std::string> shader_uniforms(Uniforms::str, end(Uniforms::str)); std::vector <std::string> shader_defines; GetShaderDefines(shader_defines); for (std::vector <GraphicsConfigPass>::const_iterator i = config.passes.begin(); i != config.passes.end(); i++) { // check conditions if (!i->conditions.Satisfied(conditions)) continue; // load pass output const std::string & outname = i->output; if (render_outputs.find(outname) == render_outputs.end()) { // collect a list of textures for the outputs std::vector <std::string> outputs = Tokenize(outname, " "); std::vector <FrameBufferTexture*> fbotex; for (std::vector <std::string>::const_iterator o = outputs.begin(); o != outputs.end(); o++) { texture_output_map_type::iterator to = texture_outputs.find(*o); if (to != texture_outputs.end()) { fbotex.push_back(&to->second); } } if (fbotex.empty()) { error_output << "None of these outputs are active: " << outname << std::endl; return false; } // initialize fbo FrameBufferObject & fbo = render_outputs[outname].RenderToFBO(); fbo.Init(glstate, fbotex, error_output); } // load pass shader const std::string & shadername = i->shader; if (shaders.find(shadername) == shaders.end()) { ConfigShaderMap::const_iterator csi = config_shaders.find(shadername); if (csi == config_shaders.end()) { error_output << "Shader not defined: " << shadername << std::endl; return false; } const GraphicsConfigShader * cs = csi->second; std::vector <std::string> defines = Tokenize(cs->defines, " "); defines.reserve(defines.size() + shader_defines.size()); defines.insert(defines.end(), shader_defines.begin(), shader_defines.end()); Shader & shader = shaders[cs->name]; if (!shader.Load( shaderpath + "/" + cs->vertex, shaderpath + "/" + cs->fragment, defines, shader_uniforms, info_output, error_output)) { return false; } } } return true; }
void GraphicsGL2::DrawScenePass( const GraphicsConfigPass & pass, std::map <std::string, PtrVector <Drawable> > & culled_static_drawlist, std::ostream & error_output) { // log failure here? if (!pass.conditions.Satisfied(conditions)) return; // setup shader shader_map_type::iterator si = shaders.find(pass.shader); if (si == shaders.end()) { ReportOnce(&pass, "Shader " + pass.shader + " couldn't be found", error_output); return; } renderscene.SetShader(&si->second); // setup textures std::vector <TextureInterface*> input_textures; GetScenePassInputTextures(pass.inputs, input_textures); renderscene.SetTextures(glstate, input_textures, error_output); // setup state renderscene.SetColorMask(glstate, pass.write_color, pass.write_alpha); renderscene.SetDepthMode(glstate, DepthModeFromString(pass.depthtest), pass.write_depth); renderscene.SetBlendMode(glstate, BlendModeFromString(pass.blendmode)); // setup output render_output_map_type::iterator oi = render_outputs.find(pass.output); if (oi == render_outputs.end()) { ReportOnce(&pass, "Render output " + pass.output + " couldn't be found", error_output); return; } RenderOutput & output = oi->second; // handle the cubemap case const bool cubemap = (output.IsFBO() && output.RenderToFBO().IsCubemap()); const int cubesides = cubemap ? 6 : 1; std::string cameraname = pass.camera; for (int cubeside = 0; cubeside < cubesides; cubeside++) { if (cubemap) { // build a name for the sub camera std::stringstream converter; converter << pass.camera << "_cubeside" << cubeside; cameraname = converter.str(); // attach the correct cube side on the render output AttachCubeSide(cubeside, output.RenderToFBO(), error_output); } // setup camera camera_map_type::iterator ci = cameras.find(cameraname); if (ci == cameras.end()) { ReportOnce(&pass, "Camera " + pass.camera + " couldn't be found", error_output); return; } renderscene.SetCamera(ci->second); // render pass draw layers output.Begin(glstate, error_output); renderscene.ClearOutput(glstate, pass.clear_color, pass.clear_depth); for (std::vector <std::string>::const_iterator d = pass.draw.begin(); d != pass.draw.end(); d++) { const std::string & layer = *d; // setup dynamic drawlist reseatable_reference <PtrVector <Drawable> > container_dynamic = dynamic_drawlist.GetByName(layer); if (!container_dynamic) { ReportOnce(&pass, "Drawable container " + layer + " couldn't be found", error_output); return; } // setup static drawlist const std::string drawlist_key = BuildKey(cameraname, layer); std::map <std::string, PtrVector <Drawable> >::const_iterator container_static = culled_static_drawlist.find(drawlist_key); if (container_static == culled_static_drawlist.end()) { ReportOnce(&pass, "Couldn't find culled static drawlist for camera/draw combination: " + drawlist_key, error_output); return; } if (!container_dynamic->empty() || !container_static->second.empty()) { renderscene.SetDrawLists(*container_dynamic, container_static->second); renderscene.Render(glstate, error_output); } } output.End(glstate, error_output); CheckForOpenGLErrors("render output end", error_output); } }