void Shader::setUniform(const std::string& name, const Glsl::Vec2& v) { UniformBinder binder(*this, name); if (binder.location != -1) glCheck(GLEXT_glUniform2f(binder.location, v.x, v.y)); }
void Texture::destroy() { glCheck(glDeleteTextures(1, &m_texture)); m_texture = 0; m_format = Format::None; }
bool Texture::loadFromImage(const Image& image, const IntRect& area) { // Retrieve the image size int width = static_cast<int>(image.getSize().x); int height = static_cast<int>(image.getSize().y); // Load the entire image if the source area is either empty or contains the whole image if (area.width == 0 || (area.height == 0) || ((area.left <= 0) && (area.top <= 0) && (area.width >= width) && (area.height >= height))) { // Load the entire image if (create(image.getSize().x, image.getSize().y)) { update(image); // Force an OpenGL flush, so that the texture will appear updated // in all contexts immediately (solves problems in multi-threaded apps) glCheck(glFlush()); return true; } else { return false; } } else { // Load a sub-area of the image // Adjust the rectangle to the size of the image IntRect rectangle = area; if (rectangle.left < 0) rectangle.left = 0; if (rectangle.top < 0) rectangle.top = 0; if (rectangle.left + rectangle.width > width) rectangle.width = width - rectangle.left; if (rectangle.top + rectangle.height > height) rectangle.height = height - rectangle.top; // Create the texture and upload the pixels if (create(rectangle.width, rectangle.height)) { // Make sure that the current texture binding will be preserved priv::TextureSaver save; // Copy the pixels to the texture, row by row const Uint8* pixels = image.getPixelsPtr() + 4 * (rectangle.left + (width * rectangle.top)); glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); for (int i = 0; i < rectangle.height; ++i) { glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.width, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); pixels += 4 * width; } // Force an OpenGL flush, so that the texture will appear updated // in all contexts immediately (solves problems in multi-threaded apps) glCheck(glFlush()); return true; } else { return false; } } }
int gfxInit() { int detectedBPP; SDL_Surface *icon; int ret; char *fileName; if (SDL_Init(SDL_INIT_VIDEO)) { conAdd(LERR, "SDL Init failed"); conAdd(LERR, SDL_GetError()); sdlCheck(); return 0; } if (TTF_Init()) { conAdd(LERR, "SDL_ttf Init failed"); conAdd(LERR, SDL_GetError()); sdlCheck(); return 0; } video.sdlStarted = 1; fileName = findFile(MISCDIR "/gravit.png"); if (!fileName) { return 0; } icon = IMG_Load(fileName); if (!icon) { sdlCheck(); } SDL_WM_SetIcon(icon, NULL); SDL_FreeSurface(icon); setTitle(0); video.gfxInfo = (SDL_VideoInfo*) SDL_GetVideoInfo(); detectedBPP = video.gfxInfo->vfmt->BitsPerPixel; conAdd(LLOW, "Detected %i BPP", detectedBPP); gfxInitRetry: if (video.screenBPP == 0) video.screenBPP = detectedBPP; ret = gfxSetResolution(); if (ret) { if (ret == 1) { if (video.screenAA) { conAdd(LERR, "You have videoantialiasing on. I'm turning it off and restarting..."); video.screenAA = 0; goto gfxInitRetry; } if (detectedBPP != video.screenBPP) { conAdd(LERR, "Your BPP setting is different to your desktop BPP. I'm restarting with your desktop BPP..."); video.screenBPP = detectedBPP; goto gfxInitRetry; } } return 0; } conAdd(LLOW, "Your video mode is %ix%ix%i", video.screenW, video.screenH, video.gfxInfo->vfmt->BitsPerPixel ); if (!video.screenAA && view.particleRenderMode == 1) { conAdd(LERR, "Warning! You don't have videoantialiasing set to 1. From what I've seen so far"); conAdd(LERR, "this might cause particlerendermode 1 not to work. If you don't see any particles"); conAdd(LERR, "after spawning, hit the \\ (backslash) key)."); } glClearColor(0, 0, 0, 0); glShadeModel(GL_SMOOTH); glEnable(GL_LINE_SMOOTH); glDisable(GL_DEPTH_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glCheck(); checkPointParameters(); checkPointSprite(); checkDriverBlacklist(); SDL_ShowCursor(view.showCursor); SDL_EnableUNICODE(SDL_ENABLE); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); #ifndef WITHOUT_AGAR AG_InitCore("gravit", 0); //AG_InitGraphics("sdlgl"); if (AG_InitVideoSDL(video.sdlScreen, AG_VIDEO_OVERLAY | AG_VIDEO_OPENGL_OR_SDL) == -1) conAdd(LERR, "agar error while initializing main window: %s", AG_GetError() ); video.agarStarted = 1; if (!view.screenSaver) osdInitDefaultWindows(); #endif return 1; }
bool Shader::compile(const char *vertexShaderCode, const char *fragmentShaderCode) { ensureGLContext(); if (!isAvailable()) { std::cerr << "Failed to create a shader. Your system doesn't support shaders. " << "You should use Shader::isAvailable() befor trying to use shaders.\n"; return false; } if (mShaderProgram) { glCheck(glDeleteObjectARB(mShaderProgram)); } mCurrentTexture = -1; mTextures.clear(); mParams.clear(); mShaderProgram = glCheck(glCreateProgramObjectARB()); if (vertexShaderCode) { GLhandleARB vertexShader = glCheck(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); glCheck(glShaderSourceARB(vertexShader, 1, &vertexShaderCode, null)); glCheck(glCompileShaderARB(vertexShader)); GLint success; glCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log)); std::cerr << "Failed to compile vertex shader. " << log << "\n"; glCheck(glDeleteObjectARB(mShaderProgram)); glCheck(glDeleteObjectARB(vertexShader)); mShaderProgram = 0; return false; } glCheck(glAttachObjectARB(mShaderProgram, vertexShader)); glCheck(glDeleteObjectARB(vertexShader)); } if (fragmentShaderCode) { GLhandleARB fragmentShader = glCheck(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); glCheck(glShaderSourceARB(fragmentShader, 1, &fragmentShaderCode, null)); glCheck(glCompileShaderARB(fragmentShader)); GLint success; glCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log)); std::cerr << "Failed to compile vertex shader. " << log << "\n"; glCheck(glDeleteObjectARB(mShaderProgram)); glCheck(glDeleteObjectARB(fragmentShader)); mShaderProgram = 0; return false; } glCheck(glAttachObjectARB(mShaderProgram, fragmentShader)); glCheck(glDeleteObjectARB(fragmentShader)); } glCheck(glLinkProgramARB(mShaderProgram)); GLint success; glCheck(glGetObjectParameterivARB(mShaderProgram, GL_OBJECT_LINK_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(mShaderProgram, sizeof(log), 0, log)); std::cerr << "Failed to link shader. " << log << "\n"; glCheck(glDeleteObjectARB(mShaderProgram)); mShaderProgram = 0; return false; } glCheck(glFlush()); return true; }
void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount, PrimitiveType type, const RenderStates& states) { // Nothing to draw? if (!vertices || (vertexCount == 0)) return; // GL_QUADS is unavailable on OpenGL ES #ifdef SFML_OPENGL_ES if (type == Quads) { err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl; return; } #define GL_QUADS 0 #endif if (activate(true)) { // First set the persistent OpenGL states if it's the very first call if (!m_cache.glStatesSet) resetGLStates(); // Check if the vertex count is low enough so that we can pre-transform them bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize); if (useVertexCache) { // Pre-transform the vertices and store them into the vertex cache for (std::size_t i = 0; i < vertexCount; ++i) { Vertex& vertex = m_cache.vertexCache[i]; vertex.position = states.transform * vertices[i].position; vertex.color = vertices[i].color; vertex.texCoords = vertices[i].texCoords; } // Since vertices are transformed, we must use an identity transform to render them if (!m_cache.useVertexCache) applyTransform(Transform::Identity); } else { applyTransform(states.transform); } // Apply the view if (m_cache.viewChanged) applyCurrentView(); // Apply the blend mode if (states.blendMode != m_cache.lastBlendMode) applyBlendMode(states.blendMode); // Apply the texture Uint64 textureId = states.texture ? states.texture->m_cacheId : 0; if (textureId != m_cache.lastTextureId) applyTexture(states.texture); // Apply the shader if (states.shader) applyShader(states.shader); // If we pre-transform the vertices, we must use our internal vertex cache if (useVertexCache) { // ... and if we already used it previously, we don't need to set the pointers again if (!m_cache.useVertexCache) vertices = m_cache.vertexCache; else vertices = NULL; } // Setup the pointers to the vertices' components if (vertices) { const char* data = reinterpret_cast<const char*>(vertices); //glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)); //glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)); //glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12)); } // Find the OpenGL primitive type static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS}; GLenum mode = modes[type]; // Draw the primitives glCheck(glDrawArrays(mode, 0, vertexCount)); // Unbind the shader, if any if (states.shader) applyShader(NULL); // If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture. // This prevents a bug where some drivers do not clear RenderTextures properly. if (states.texture && states.texture->m_fboAttachment) applyTexture(NULL); // Update the cache m_cache.useVertexCache = useVertexCache; } }
bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) { ensureGlContext(); // First make sure that we can use shaders if (!isAvailable()) { err() << "Failed to create a shader: your system doesn't support shaders " << "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl; return false; } // Destroy the shader if it was already created if (m_shaderProgram) glCheck(glDeleteObjectARB(m_shaderProgram)); // Create the program m_shaderProgram = glCreateProgramObjectARB(); // Create the vertex shader if needed if (vertexShaderCode) { // Create and compile the shader GLhandleARB vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); glCheck(glShaderSourceARB(vertexShader, 1, &vertexShaderCode, NULL)); glCheck(glCompileShaderARB(vertexShader)); // Check the compile log GLint success; glCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log)); err() << "Failed to compile vertex shader:" << std::endl << log << std::endl; glCheck(glDeleteObjectARB(vertexShader)); glCheck(glDeleteObjectARB(m_shaderProgram)); m_shaderProgram = 0; return false; } // Attach the shader to the program, and delete it (not needed anymore) glCheck(glAttachObjectARB(m_shaderProgram, vertexShader)); glCheck(glDeleteObjectARB(vertexShader)); } // Create the fragment shader if needed if (fragmentShaderCode) { // Create and compile the shader GLhandleARB fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); glCheck(glShaderSourceARB(fragmentShader, 1, &fragmentShaderCode, NULL)); glCheck(glCompileShaderARB(fragmentShader)); // Check the compile log GLint success; glCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log)); err() << "Failed to compile fragment shader:" << std::endl << log << std::endl; glCheck(glDeleteObjectARB(fragmentShader)); glCheck(glDeleteObjectARB(m_shaderProgram)); m_shaderProgram = 0; return false; } // Attach the shader to the program, and delete it (not needed anymore) glCheck(glAttachObjectARB(m_shaderProgram, fragmentShader)); glCheck(glDeleteObjectARB(fragmentShader)); } // Link the program glCheck(glLinkProgramARB(m_shaderProgram)); // Check the link log GLint success; glCheck(glGetObjectParameterivARB(m_shaderProgram, GL_OBJECT_LINK_STATUS_ARB, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(glGetInfoLogARB(m_shaderProgram, sizeof(log), 0, log)); err() << "Failed to link shader:" << std::endl << log << std::endl; glCheck(glDeleteObjectARB(m_shaderProgram)); m_shaderProgram = 0; return false; } return true; }
void RenderTarget::resetGLStates() { // Check here to make sure a context change does not happen after activate(true) bool shaderAvailable = Shader::isAvailable(); if (activate(true)) { // Make sure that extensions are initialized priv::ensureExtensionsInit(); // Make sure that the texture unit which is active is the number 0 if (GLEXT_multitexture) { glCheck(GLEXT_glClientActiveTexture(GLEXT_GL_TEXTURE0)); glCheck(GLEXT_glActiveTexture(GLEXT_GL_TEXTURE0)); } // Define the default OpenGL states glCheck(glDisable(GL_CULL_FACE)); glCheck(glDisable(GL_LIGHTING)); glCheck(glDisable(GL_DEPTH_TEST)); glCheck(glDisable(GL_ALPHA_TEST)); glCheck(glEnable(GL_TEXTURE_2D)); glCheck(glEnable(GL_BLEND)); glCheck(glMatrixMode(GL_MODELVIEW)); glCheck(glEnableClientState(GL_VERTEX_ARRAY)); glCheck(glEnableClientState(GL_COLOR_ARRAY)); glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); m_cache.glStatesSet = true; // Apply the default SFML states applyBlendMode(BlendAlpha); applyTransform(Transform::Identity); applyTexture(NULL); if (shaderAvailable) applyShader(NULL); m_cache.useVertexCache = false; // Set the default view setView(getView()); } }
void RenderTarget::applyTransform(const Transform& transform) { // No need to call glMatrixMode(GL_MODELVIEW), it is always the // current mode (for optimization purpose, since it's the most used) glCheck(glLoadMatrixf(transform.getMatrix())); }
void Shader::setUniformArray(const std::string& name, const float* scalarArray, std::size_t length) { UniformBinder binder(*this, name); if (binder.location != -1) glCheck(GLEXT_glUniform1fv(binder.location, length, scalarArray)); }
bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) { ensureGlContext(); // First make sure that we can use shaders if (!isAvailable()) { err() << "Failed to create a shader: your system doesn't support shaders " << "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl; return false; } // Destroy the shader if it was already created if (m_shaderProgram) { glCheck(GLEXT_glDeleteObject(castToGlHandle(m_shaderProgram))); m_shaderProgram = 0; } // Reset the internal state m_currentTexture = -1; m_textures.clear(); m_uniforms.clear(); // Create the program GLEXT_GLhandle shaderProgram; glCheck(shaderProgram = GLEXT_glCreateProgramObject()); // Create the vertex shader if needed if (vertexShaderCode) { // Create and compile the shader GLEXT_GLhandle vertexShader; glCheck(vertexShader = GLEXT_glCreateShaderObject(GLEXT_GL_VERTEX_SHADER)); glCheck(GLEXT_glShaderSource(vertexShader, 1, &vertexShaderCode, NULL)); glCheck(GLEXT_glCompileShader(vertexShader)); // Check the compile log GLint success; glCheck(GLEXT_glGetObjectParameteriv(vertexShader, GLEXT_GL_OBJECT_COMPILE_STATUS, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(GLEXT_glGetInfoLog(vertexShader, sizeof(log), 0, log)); err() << "Failed to compile vertex shader:" << std::endl << log << std::endl; glCheck(GLEXT_glDeleteObject(vertexShader)); glCheck(GLEXT_glDeleteObject(shaderProgram)); return false; } // Attach the shader to the program, and delete it (not needed anymore) glCheck(GLEXT_glAttachObject(shaderProgram, vertexShader)); glCheck(GLEXT_glDeleteObject(vertexShader)); } // Create the fragment shader if needed if (fragmentShaderCode) { // Create and compile the shader GLEXT_GLhandle fragmentShader; glCheck(fragmentShader = GLEXT_glCreateShaderObject(GLEXT_GL_FRAGMENT_SHADER)); glCheck(GLEXT_glShaderSource(fragmentShader, 1, &fragmentShaderCode, NULL)); glCheck(GLEXT_glCompileShader(fragmentShader)); // Check the compile log GLint success; glCheck(GLEXT_glGetObjectParameteriv(fragmentShader, GLEXT_GL_OBJECT_COMPILE_STATUS, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(GLEXT_glGetInfoLog(fragmentShader, sizeof(log), 0, log)); err() << "Failed to compile fragment shader:" << std::endl << log << std::endl; glCheck(GLEXT_glDeleteObject(fragmentShader)); glCheck(GLEXT_glDeleteObject(shaderProgram)); return false; } // Attach the shader to the program, and delete it (not needed anymore) glCheck(GLEXT_glAttachObject(shaderProgram, fragmentShader)); glCheck(GLEXT_glDeleteObject(fragmentShader)); } // Link the program glCheck(GLEXT_glLinkProgram(shaderProgram)); // Check the link log GLint success; glCheck(GLEXT_glGetObjectParameteriv(shaderProgram, GLEXT_GL_OBJECT_LINK_STATUS, &success)); if (success == GL_FALSE) { char log[1024]; glCheck(GLEXT_glGetInfoLog(shaderProgram, sizeof(log), 0, log)); err() << "Failed to link shader:" << std::endl << log << std::endl; glCheck(GLEXT_glDeleteObject(shaderProgram)); return false; } m_shaderProgram = castFromGlHandle(shaderProgram); // Force an OpenGL flush, so that the shader will appear updated // in all contexts immediately (solves problems in multi-threaded apps) glCheck(glFlush()); return true; }
void Shader::setUniform(const std::string& name, const Glsl::Mat4& matrix) { UniformBinder binder(*this, name); if (binder.location != -1) glCheck(GLEXT_glUniformMatrix4fv(binder.location, 1, GL_FALSE, matrix.array)); }
void Shader::setUniform(const std::string& name, const Glsl::Ivec4& v) { UniformBinder binder(*this, name); if (binder.location != -1) glCheck(GLEXT_glUniform4i(binder.location, v.x, v.y, v.z, v.w)); }
void Shader::setUniform(const std::string& name, int x) { UniformBinder binder(*this, name); if (binder.location != -1) glCheck(GLEXT_glUniform1i(binder.location, x)); }
//------------------------------------------------------------------------------ bool ShaderProgram::loadFromSourceCode(const std::unordered_map<ShaderType, std::string> & sources) { // Check if none of the sources is empty if (sources.empty()) { SN_ERROR("ShaderProgram::loadFromSourceCode: source code is empty"); return false; } for (auto it = sources.begin(); it != sources.end(); ++it) { if (it->second.empty()) { SN_ERROR("ShaderProgram::loadFromSourceCode: source code is empty for shader type " << toString(it->first)); return false; } } // Deletes the old program if it was already loaded unload(); // Reset uniforms because they might change if the shader is reloading m_uniforms.clear(); // Create shaders GLuint sID; for (auto it = sources.begin(); it != sources.end(); ++it) { ShaderType shaderType = it->first; if (!loadShaderFromSourceCode(sID, shaderType, it->second)) { // Error unload(); return false; } if (static_cast<u32>(shaderType) >= m_shaders.size()) // Note: enums are ints, not uints m_shaders.resize(shaderType + 1, nullptr); m_shaders[shaderType] = new Shader(sID); } // Link shaders into a program SN_LOG("linking shader program..."); m_programID = glCreateProgram(); // TODO Verify output value? // Attach shaders to the program for (auto it = m_shaders.begin(); it != m_shaders.end(); ++it) { Shader * shader = *it; if (shader) { glCheck(glAttachShader(m_programID, shader->ID)); } } // Generic input shader variables glCheck(glBindAttribLocation(m_programID, VertexAttribute::USE_POSITION, "in_Position")); glCheck(glBindAttribLocation(m_programID, VertexAttribute::USE_COLOR, "in_Color")); glCheck(glBindAttribLocation(m_programID, VertexAttribute::USE_TEXCOORD, "in_TexCoord")); glCheck(glBindAttribLocation(m_programID, VertexAttribute::USE_NORMAL, "in_Normal")); // Link glCheck(glLinkProgram(m_programID)); // Check errors GLint isLinked = 0; glCheck(glGetProgramiv(m_programID, GL_LINK_STATUS, &isLinked)); if (isLinked != GL_TRUE) { // Retrieve error log size GLint errorSize = 0; glCheck(glGetProgramiv(m_programID, GL_INFO_LOG_LENGTH, &errorSize)); // This string will contain the error message char * errorStr = new char[errorSize + 1]; errorStr[errorSize] = '\0'; // Retrieve the error log glCheck(glGetProgramInfoLog(m_programID, errorSize, &errorSize, errorStr)); // Display the error SN_ERROR("ShaderProgram::load: Link error(s)."); SN_ERROR(errorStr); // Free memory and return delete[] errorStr; unload(); // Rollback return false; // Error } return true; // Fine ! }
void Shader::unbind() const { ensureGlContext(); glCheck(glUseProgramObjectARB(0)); }
void sdl_window::do_activate_context() const { if (SDL_GL_MakeCurrent(iHandle, iContext) != 0) throw failed_to_activate_opengl_context(SDL_GetError()); glCheck(""); }
int loadFonts() { TTF_Font *font = NULL; SDL_Surface *fontSurface = NULL; SDL_Surface *tmp = NULL; static SDL_Color fontColour = {255,255,255}; char letter[2]; int i; char *p; letter[1] = 0; p = va("%s/%s", MISCDIR, video.fontFile); if (!fileExists(p)) { conAdd(LERR, "Could not open %s", p); return 0; } font = TTF_OpenFont(p, video.fontSize); if (!font) { conAdd(LERR, "Could not open %s", p); return 0; } TTF_SetFontStyle(font, TTF_STYLE_NORMAL); memset(fonts, 0, sizeof(fonts)); fontHeight = 0; for (i = 32; i < 128; i++) { letter[0] = i; fontSurface = TTF_RenderText_Solid(font, letter, fontColour); if (!fontSurface) { TTF_CloseFont(font); return 0; } fonts[i].ow = fontSurface->w; fonts[i].oh = fontSurface->h; if (fonts[i].oh > fontHeight) fontHeight = (float)fonts[i].oh; fonts[i].w = gfxPowerOfTwo(fonts[i].ow); fonts[i].h = gfxPowerOfTwo(fonts[i].oh); if (fonts[i].w > fonts[i].h) fonts[i].h = fonts[i].w; if (fonts[i].h > fonts[i].w) fonts[i].w = fonts[i].h; tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, fonts[i].w, fonts[i].h, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); if (!tmp) { TTF_CloseFont(font); SDL_FreeSurface(fontSurface); return 0; } if (SDL_BlitSurface(fontSurface, NULL, tmp, NULL)) { TTF_CloseFont(font); SDL_FreeSurface(tmp); SDL_FreeSurface(fontSurface); return 0; } glGenTextures(1, &fonts[i].id); glCheck(); glBindTexture(GL_TEXTURE_2D, fonts[i].id); glCheck(); glTexImage2D(GL_TEXTURE_2D, 0, 3, fonts[i].w, fonts[i].h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp->pixels); glCheck(); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glCheck(); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glCheck(); SDL_FreeSurface(tmp); SDL_FreeSurface(fontSurface); } TTF_CloseFont(font); return 1; }
void VertexBuffer::data(const void* pointer, GLsizeiptr size, BufferUsage usage) { glCheck(gl::BindBuffer(gl::ARRAY_BUFFER, id())); glCheck(gl::BufferData(gl::ARRAY_BUFFER, size, pointer, static_cast<GLenum>(usage))); glCheck(gl::BindBuffer(gl::ARRAY_BUFFER, 0)); }
//------------------------------------------------------------------------------ void ShaderProgram::setParam(const std::string & name, f32 value) { glCheck(glUniform1f(getUniformLocation(name), value)); }
int loadFonts() { TTF_Font *font = NULL; SDL_Surface *fontSurface = NULL; SDL_Surface *tmp = NULL; Uint32 saved_flags; Uint8 saved_alpha; static SDL_Color fontColour = {255,255,255}; char letter[2]; int i; char *p; letter[1] = 0; p = findFile(va("%s/%s", MISCDIR, video.fontFile)); if (!p) { conAdd(LERR, "Could not open font"); return 0; } font = TTF_OpenFont(p, video.fontSize); if (!font) { conAdd(LERR, "Could not open %s", p); return 0; } TTF_SetFontStyle(font, TTF_STYLE_NORMAL); #ifdef TTF_HINTING_NORMAL TTF_SetFontHinting(font, TTF_HINTING_NORMAL); #endif memset(fonts, 0, sizeof(fonts)); fontHeight = 0; for (i = 32; i < 128; i++) { letter[0] = i; fontSurface = TTF_RenderText_Blended(font, letter, fontColour); if (!fontSurface) { #ifdef WIN32 MessageBox(NULL, TTF_GetError(), "gravit: font engine error", MB_OK); #else printf("%s\n", TTF_GetError()); #endif TTF_CloseFont(font); return 0; } fonts[i].ow = fontSurface->w; fonts[i].oh = fontSurface->h; if (fonts[i].oh > fontHeight) fontHeight = (float)fonts[i].oh; fonts[i].w = gfxPowerOfTwo(fonts[i].ow); fonts[i].h = gfxPowerOfTwo(fonts[i].oh); if (fonts[i].w > fonts[i].h) fonts[i].h = fonts[i].w; if (fonts[i].h > fonts[i].w) fonts[i].w = fonts[i].h; tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, fonts[i].w, fonts[i].h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks depend on byteorder */ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); #endif if (!tmp) { TTF_CloseFont(font); SDL_FreeSurface(fontSurface); return 0; } /* Save the alpha blending attributes */ saved_flags = fontSurface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK); #if SDL_VERSION_ATLEAST(1, 3, 0) SDL_GetSurfaceAlphaMod(fontSurface, &saved_alpha); SDL_SetSurfaceAlphaMod(fontSurface, 0xFF); #else saved_alpha = fontSurface->format->alpha; if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { SDL_SetAlpha(fontSurface, 0, 0); } #endif /* copy to texture surface */ if (SDL_BlitSurface(fontSurface, NULL, tmp, NULL)) { TTF_CloseFont(font); SDL_FreeSurface(tmp); SDL_FreeSurface(fontSurface); return 0; } glGenTextures(1, &fonts[i].id); glCheck(); glBindTexture(GL_TEXTURE_2D, fonts[i].id); glCheck(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fonts[i].w, fonts[i].h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp->pixels); glCheck(); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glCheck(); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glCheck(); SDL_FreeSurface(tmp); SDL_FreeSurface(fontSurface); } TTF_CloseFont(font); return 1; }
//------------------------------------------------------------------------------ void ShaderProgram::setParam(const std::string & name, f32 x, f32 y) { glCheck(glUniform2f(getUniformLocation(name), x, y)); }
void drawFrame() { particle_t *p; particleDetail_t *pd; int i,j,k; float c; float sc[4]; if (!state.particleHistory) return; switch (view.blendMode) { case 0: glDisable(GL_BLEND); break; case 1: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case 2: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; case 3: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE); break; case 4: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA); break; } if (view.particleRenderMode == 0) { float pointRange[2]; glDisable(GL_DEPTH_TEST); glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_POINT_SMOOTH); glGetFloatv(GL_POINT_SIZE_RANGE, pointRange); if (view.particleSizeMin < pointRange[0]) { view.particleSizeMin = pointRange[0]; conAdd(LNORM, "Point Size has reached its minimum of %f", view.particleSizeMin); } if (view.particleSizeMin > pointRange[1]) { view.particleSizeMin = pointRange[1]; conAdd(LNORM, "Point Size has reached its maximum of %f", view.particleSizeMin); } glPointSize(view.particleSizeMin); } if (view.particleRenderMode == 1) { float quadratic[] = { 0.0f, 0.0f, 0.01f }; if (!video.supportPointParameters || !video.supportPointSprite) { conAdd(LNORM, "Sorry, Your video card does not support GL_ARB_point_parameters and/or GL_ARB_point_sprite."); conAdd(LNORM, "This means you can't have really pretty looking particles."); conAdd(LNORM, "Setting particleRenderMode to 2"); view.particleRenderMode = 2; return; } glDisable(GL_DEPTH_TEST); glDisable(GL_POINT_SMOOTH); // enabling this makes particles dissapear glPointParameterfvARB_ptr( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic ); glPointParameterfARB_ptr( GL_POINT_SIZE_MAX_ARB, view.particleSizeMax ); glPointParameterfARB_ptr( GL_POINT_SIZE_MIN_ARB, view.particleSizeMin ); glPointSize( view.particleSizeMax ); // lets you put textures on the sprite // doesn't work on some cards for some reason :( // so i had to make textures an option with this mode if (view.particleRenderTexture) { glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE ); glBindTexture(GL_TEXTURE_2D, particleTextureID); } else { glBindTexture(GL_TEXTURE_2D, 0); } glEnable( GL_POINT_SPRITE_ARB ); } else if (view.particleRenderMode == 2) { glDisable(GL_DEPTH_TEST); if (view.particleRenderTexture) { glBindTexture(GL_TEXTURE_2D, particleTextureID); } else { glBindTexture(GL_TEXTURE_2D, 0); } } if (view.particleRenderMode == 0 || view.particleRenderMode == 1) { glBegin(GL_POINTS); for (i = 0; i < state.particleCount; i++) { VectorNew(pos); pd = state.particleDetail + i; glColor4fv(pd->col); if (view.frameSkip < 0) { particleInterpolate(i, ((float)view.frameSkipCounter / view.frameSkip), pos); glVertex3fv(pos); } else { p = state.particleHistory + state.particleCount * state.currentFrame + i; glVertex3fv(p->pos); } view.vertices++; } glEnd(); } else if (view.particleRenderMode == 2) { // my math mojo is not so great, so this may not be the most efficient way of doing this // this whole bit is dodgy too, as long as it works :) GLdouble matProject[16]; GLdouble matModelView[16]; GLint viewport[4]; GLdouble screen[3]; glMatrixMode(GL_PROJECTION); glPushMatrix(); glCheck(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glCheck(); glGetDoublev(GL_PROJECTION_MATRIX, matProject); glCheck(); glGetDoublev(GL_MODELVIEW_MATRIX, matModelView); glCheck(); glGetIntegerv(GL_VIEWPORT, viewport); glCheck(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (view.stereoMode == 1) { if (view.stereoModeCurrentBit == 0) { glOrtho(0.0,video.screenW/2,0,video.screenH,-1.0,1.0); } else { glOrtho(video.screenW/2,video.screenW,0,video.screenH,-1.0,1.0); } } else { glOrtho(0.0f,video.screenW,0,video.screenH,-1.0f,1.0f); } glCheck(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glCheck(); for (i = 0; i < state.particleCount; i++) { double size; VectorNew(moo); float *pos; int success; pos = moo; pd = state.particleDetail + i; if (view.frameSkip < 0) { particleInterpolate(i, ((float)view.frameSkipCounter / view.frameSkip), moo); } else { p = state.particleHistory + state.particleCount * state.currentFrame + i; pos = p->pos; } success = gluProject( pos[0],pos[1],pos[2], matModelView, matProject, viewport, &screen[0], &screen[1], &screen[2] ); if ((success != GL_TRUE) || (screen[2] > 1)) continue; size = view.particleSizeMin + (1.f - (float)screen[2]) * view.particleSizeMax; glBegin(GL_QUADS); glColor4fv(pd->col); glTexCoord2i(0,0); glVertex2d(screen[0]-size, screen[1]-size); glTexCoord2i(1,0); glVertex2d(screen[0]+size, screen[1]-size); glTexCoord2i(1,1); glVertex2d(screen[0]+size, screen[1]+size); glTexCoord2i(0,1); glVertex2d(screen[0]-size, screen[1]+size); glEnd(); view.vertices += 4; } glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); } if (view.particleRenderMode == 1 && video.supportPointParameters && video.supportPointSprite) { glDisable( GL_POINT_SPRITE_ARB ); } glBindTexture(GL_TEXTURE_2D, 0); // sc[3] = 1; if (view.tailLength > 0 || view.tailLength == -1) { // Not sure why this helps but, // it is a fix for one case where only points are drawn instead of lines // on radeon 9600 after switching to particlerendermode 0 from 1 if (view.particleRenderMode == 0) glLineWidth(view.tailWidth+1); glLineWidth(view.tailWidth); for (i = 0; i < state.particleCount; i++) { int to; p = 0; glBegin(GL_LINE_STRIP); if (view.tailLength == -1) k = 0; else if (state.currentFrame < (view.tailLength+2)) k = 0; else k = state.currentFrame - (view.tailLength+2); if (state.mode & SM_RECORD) to = state.currentFrame; else to = state.currentFrame + 1; for (j = k; j <= state.currentFrame; j+=view.tailSkip ) { //for (j = state.currentFrame; j >= k; j-=view.tailSkip ) { if (j >= state.historyFrames) continue; pd = state.particleDetail + i; if (view.tailFaded) c = (float)(j-k) / (float)(state.currentFrame-k) * view.tailOpacity; else c = view.tailOpacity; memcpy(sc, pd->col, sizeof(float)*4); sc[3] *= c; glColor4fv(sc); p = state.particleHistory + state.particleCount * j + i; glVertex3fv(p->pos); view.vertices++; } if (view.frameSkip < 0 && !(state.mode & SM_RECORD)) { VectorNew(pos); particleInterpolate(i, ((float)view.frameSkipCounter / view.frameSkip), pos); glVertex3fv(pos); } else { p = state.particleHistory + state.particleCount * state.currentFrame + i; glVertex3fv(p->pos); } glEnd(); } } }
//------------------------------------------------------------------------------ void ShaderProgram::setParam(const std::string & name, f32 x, f32 y, f32 z, f32 w) { glCheck(glUniform4f(getUniformLocation(name), x, y, z, w)); }
void RenderTextureImplFBO::updateTexture(unsigned int) { glCheck(glFlush()); }
//------------------------------------------------------------------------------ void ShaderProgram::setParam(const std::string & name, const f32 matrixValues[16], bool transpose) { glCheck(glUniformMatrix4fv(getUniformLocation(name), 1, transpose, matrixValues)); }
void Texture::unbind(const unsigned int texUnit) const { glCheck(glActiveTexture(GL_TEXTURE0 + texUnit)); glCheck(glBindTexture(m_target, 0)); }
//------------------------------------------------------------------------------ void ShaderProgram::setParam(const std::string & name, s32 i) { glCheck(glUniform1i(getUniformLocation(name), i)); }
Texture::~Texture() { glCheck(glDeleteTextures(1, &tex)); }
//////////////////////////////////////////////////////////// /// \brief Destructor: restore state after uniform is set /// //////////////////////////////////////////////////////////// ~UniformBinder() { // Disable program object if (currentProgram && (currentProgram != savedProgram)) glCheck(GLEXT_glUseProgramObject(savedProgram)); }