尽管从 learnopengl in practice 部分复制了代码,但我在渲染精灵时遇到了问题。一开始我以为什么都没有渲染,但在从黑色变成青色之后我发现纹理实际上是生成的但它是一个漆黑的矩形而不是所谓的“令人敬畏的脸”的恼人的开放微笑沐浴在这家喻户晓的电脑绿中。我尝试并尝试在线搜索解决方案,但是当您阅读本文时,您已经知道它的结果是什么,所以我以全能上帝的名义请求大家帮助我解决这个麻烦的事情,我恳求。
我正在使用 glew 和 SDL 的邪恶组合,所以这是愚蠢的代码:
着色器
#pragma once
#define GLEW_STATIC
#include <gl/glew-2.2.0/include/GL/glew.h>
#include <glm-master/glm/gtc/type_ptr.hpp>
#include <iostream>
#include <fstream>
#include <istream>
#include <sstream>
class shader
{
public:
unsigned int prog;
shader()
{
}
void lammp(const char* vertexchar, const char* fragmentchar, const char* geochar)
{
unsigned int vex, fra;
unsigned int geo;
char info[512];
int success;
vex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vex, 1, &vertexchar, NULL);
glCompileShader(vex);
glGetShaderiv(vex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vex, 512, NULL, info);
std::cout << "problem: " << info << "... szmato" << std::endl;
}
fra = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fra, 1, &fragmentchar, NULL);
glCompileShader(fra);
glGetShaderiv(fra, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fra, 512, NULL, info);
std::cout << "problem: " << info << "... szmato" << std::endl;
}
prog = glCreateProgram();
glAttachShader(prog, vex);
glAttachShader(prog, fra);
if (geochar != NULL)
{
geo = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geo, 1, &geochar, NULL);
glCompileShader(geo);
glGetShaderiv(geo, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fra, 512, NULL, info);
std::cout << "problem: " << info << "... szmato" << std::endl;
}
glAttachShader(prog, geo);
}
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(prog, 512, NULL, info);
std::cout << "lol program się zesrał: " << info << " laudetur iesus christus" << std::endl;
}
glDeleteShader(vex);
glDeleteShader(fra);
if (geochar != NULL)
{
glDeleteShader(geo);
}
}
shader &use()
{
glUseProgram(prog);
return *this;
}
void SetFloat(const char* name, float value, bool useShader)
{
if (useShader)
this->use();
glUniform1f(glGetUniformLocation(this->prog, name), value);
}
void SetInteger(const char* name, int value, bool useShader)
{
if (useShader)
this->use();
glUniform1i(glGetUniformLocation(this->prog, name), value);
}
void SetVector2f(const char* name, float x, float y, bool useShader)
{
if (useShader)
this->use();
glUniform2f(glGetUniformLocation(this->prog, name), x, y);
}
void SetVector2f(const char* name, const glm::vec2& value, bool useShader)
{
if (useShader)
this->use();
glUniform2f(glGetUniformLocation(this->prog, name), value.x, value.y);
}
void SetVector3f(const char* name, float x, float y, float z, bool useShader)
{
if (useShader)
this->use();
glUniform3f(glGetUniformLocation(this->prog, name), x, y, z);
}
void SetVector3f(const char* name, const glm::vec3& value, bool useShader)
{
if (useShader)
this->use();
glUniform3f(glGetUniformLocation(this->prog, name), value.x, value.y, value.z);
}
void SetVector4f(const char* name, float x, float y, float z, float w, bool useShader)
{
if (useShader)
this->use();
glUniform4f(glGetUniformLocation(this->prog, name), x, y, z, w);
}
void SetVector4f(const char* name, const glm::vec4& value, bool useShader)
{
if (useShader)
this->use();
glUniform4f(glGetUniformLocation(this->prog, name), value.x, value.y, value.z, value.w);
}
void SetMatrix4(const char* name, const glm::mat4& matrix, bool useShader)
{
if (useShader)
this->use();
glUniformMatrix4fv(glGetUniformLocation(this->prog, name), 1, false, glm::value_ptr(matrix));
}
};
雪碧
#pragma once
#include "shader.h"
class skin2D
{
public:
unsigned int ID;
unsigned int Width, Height;
unsigned int Internal_Format;
unsigned int Image_Format;
unsigned int Wrap_S;
unsigned int Wrap_T;
unsigned int Filter_Min;
unsigned int Filter_Max;
skin2D()
{
glGenTextures(1, &this->ID);
}
void Generate(unsigned int width, unsigned int height, unsigned char* data)
{
this->Width = width;
this->Height = height;
glBindTexture(GL_TEXTURE_2D, this->ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Bind() const
{
glBindTexture(GL_TEXTURE_2D, this->ID);
}
};
精灵渲染器
class skinmaker
{
// Render state
shader shaqer;
unsigned int quadVAO;
// Initializes and configures the quad's buffer and vertex attributes
void initRenderData()
{
unsigned int VBO;
float vertices[] = {
// pos // tex
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 0.0f
};
glGenVertexArrays(1, &this->quadVAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(this->quadVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public:
// Constructor (inits shaders/shapes)
skinmaker(shader shaber)
{
this->shaqer = shaber;
this->initRenderData();
}
// Destructor
~skinmaker();
// Renders a defined quad textured with given sprite
void IeatCrayons(skin2D& texture, glm::vec2 position, glm::vec2 size = glm::vec2(10.0f, 10.0f), float rotate = 0.0f, glm::vec3 color = glm::vec3(1.0f))
{
this->shaqer.use();
glm::mat4 model =
glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(position, 0.0f)); // first translate (transformations are: scale happens first, then rotation, and then final translation happens; reversed order)
model = glm::translate(model, glm::vec3(0.5f * size.x, 0.5f * size.y, 0.0f)); // move origin of rotation to center of quad
model = glm::rotate(model, glm::radians(rotate), glm::vec3(0.0f, 0.0f, 1.0f)); // then rotate
model = glm::translate(model, glm::vec3(-0.5f * size.x, -0.5f * size.y, 0.0f)); // move origin back
model = glm::scale(model, glm::vec3(size, 1.0f)); // last scale
this->shaqer.SetMatrix4("model", model, false);
// render textured quad
this->shaqer.SetVector3f("spriteColor", color, false);
glActiveTexture(GL_TEXTURE0);
texture.Bind();
glBindVertexArray(this->quadVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
};
资源管理器
#pragma once
#include <map>
#include <string>
#include "skin.h"
#include "shader.h"
#include "stb_image.h"
#include <iostream>
#include <sstream>
#include <fstream>
class ResourceManager
{
public:
static std::map<std::string, shader> Shaders;
static std::map<std::string, skin2D> Textures;
static shader LoadShader(const char* vShaderFile, const char* fShaderFile, const char* gShaderFile, std::string name)
{
Shaders[name] = loadShaderFromFile(vShaderFile, fShaderFile, gShaderFile);
return Shaders[name];
}
static shader GetShader(std::string name)
{
return Shaders[name];
}
static skin2D LoadTexture(const char* file, bool alpha, std::string name)
{
Textures[name] = loadTextureFromFile(file, alpha);
return Textures[name];
}
static skin2D& GetTexture(std::string name);
static void Clear()
{
for (auto iter : Shaders)
glDeleteProgram(iter.second.prog);
for (auto iter : Textures)
glDeleteTextures(1, &iter.second.ID);
}
private:
ResourceManager() { }
static shader loadShaderFromFile(const char* vShaderFile, const char* fShaderFile, const char* gShaderFile = nullptr)
{
std::string vertexCode;
std::string fragmentCode;
std::string geometryCode;
try
{
// open files
std::ifstream vertexShaderFile(vShaderFile);
std::ifstream fragmentShaderFile(fShaderFile);
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vertexShaderFile.rdbuf();
fShaderStream << fragmentShaderFile.rdbuf();
// close file handlers
vertexShaderFile.close();
fragmentShaderFile.close();
// convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
// if geometry shader path is present, also load a geometry shader
if (gShaderFile != nullptr)
{
std::ifstream geometryShaderFile(gShaderFile);
std::stringstream gShaderStream;
gShaderStream << geometryShaderFile.rdbuf();
geometryShaderFile.close();
geometryCode = gShaderStream.str();
}
}
catch (std::exception e)
{
std::cout << "ERROR::SHADER: Failed to read shader files" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
const char* gShaderCode = geometryCode.c_str();
// 2. now create shader object from source code
shader shaqer;
shaqer.lammp(vShaderCode, fShaderCode, gShaderFile != nullptr ? gShaderCode : nullptr);
return shaqer;
}
static skin2D loadTextureFromFile(const char* file, bool alpha);
};
这是个愚蠢的 .CCP 文件
#include "resouces.h"
std::map<std::string, shader> ResourceManager::Shaders;
std::map<std::string, skin2D> ResourceManager::Textures;
skin2D ResourceManager::loadTextureFromFile(const char* file, bool alpha)
{
// create texture object
skin2D texture;
if (alpha)
{
texture.Internal_Format = GL_RGBA;
texture.Image_Format = GL_RGBA;
}
// load image
int width, height, nrChannels;
unsigned char* data = stbi_load(file, &width, &height, &nrChannels, 0);
// now generate texture
texture.Generate(width, height, data);
// and finally free image data
stbi_image_free(data);
return texture;
}
skin2D& ResourceManager::GetTexture(std::string name)
{
skin2D& skin = Textures[name];
return skin;
}
这里是主要代码 YUPII! (免除我这种自我强加的痛苦)
#define GLEW_STATIC
#include <gl/glew-2.2.0/include/GL/glew.h>
#define STB_IMAGE_IMPLEMENTATION
#include "window.h"
#include "InputMenager.h"
#include "shader.h"
#include "resouces.h"
#include "glm-master/glm/glm.hpp"
#undef main
int main()
{
int Width = 800, Height = 600;
window w = window("Praise to God!", Width, Height);
glewInit();
InputMen in;
bool e = false;
skinmaker* Renderer;
ResourceManager::LoadShader("Shaders/shader.vs", "Shaders/shader.frag", nullptr, "sprite");
// configure shaders
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(Width),static_cast<float>(Height), 0.0f, -1.0f, 1.0f);
ResourceManager::GetShader("sprite").use().SetInteger("image", 0, true);
ResourceManager::GetShader("sprite").SetMatrix4("projection", projection, true);
// set render-specific controls
Renderer = new skinmaker(ResourceManager::GetShader("sprite"));
// load textures
ResourceManager::LoadTexture("awesomeface.png", true, "face");
while (!e)
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
Renderer->IeatCrayons(ResourceManager::GetTexture("face"), glm::vec2(200.0f, 100.0f), glm::vec2(300.0f, 400.0f), 45.0f);
w.Display();
while (SDL_PollEvent(&in.input) != NULL)
{
if (in.ButtonDown(SDL_SCANCODE_SPACE)) e = true;
}
}
}
所以我请大家帮我解决这个对你来说可能是轻而易举的麻烦事, 所以请告诉我我的错是什么我做错了什么或者我忘记了什么,无论如何如果你还在读这篇文章上帝保佑你并感谢你提供的任何帮助
如果您不生成mipmaps(使用
glGenerateMipmap
),设置GL_TEXTURE_MIN_FILTER
很重要。由于默认过滤器是 GL_NEAREST_MIPMAP_LINEAR
,如果您不将最小化功能更改为 GL_NEAREST
或 GL_LINEAR
,则纹理将是“Mipmap 不完整”。
Wrap_S
对象(类Wrap_T
)的Filter_Min
、Filter_Max
、Texture
和skin2D
属性永远不会被设置。我建议使用适当的默认值设置属性:
class skin2D
{
public:
unsigned int ID = 0;
unsigned int Width = 0,
unsigned int Height = 0;
unsigned int Internal_Format = GL_RGBA;
unsigned int Image_Format = GL_RGBA;
unsigned int Wrap_S = GL_REPEAT;
unsigned int Wrap_T = GL_REPEAT;
unsigned int Filter_Min = GL_LINEAR_MIPMAP_LINEAR;
unsigned int Filter_Max = GL_LINEAR;
skin2D()
{
glGenTextures(1, &this->ID);
}
void Generate(unsigned int width, unsigned int height, unsigned char* data)
{
this->Width = width;
this->Height = height;
glBindTexture(GL_TEXTURE_2D, this->ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
// [...]