Basic (non-sorted) transparent rendering and cleanup in RenderSystem

This commit is contained in:
karl 2020-01-15 00:20:48 +01:00
parent cbb0dc1164
commit a043847bad
8 changed files with 76 additions and 20 deletions

View File

@ -47,7 +47,7 @@ struct Mesh {
glBindVertexArray(0);
}
void render() {
void render() const {
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, 0);

View File

@ -8,30 +8,53 @@
#include "../../Util/stb_image.h"
struct Texture {
explicit Texture(const std::string& path) {
struct Settings {
Settings(bool mipmaps, bool transparent) : mipmaps(mipmaps), transparent(transparent) {}
bool mipmaps = true;
bool transparent = false;
};
explicit Texture(const std::string& path, Settings settings) {
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Mipmapping
if (settings.mipmaps) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0);
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D); // Mipmapping
// Alpha channel?
unsigned int glChannels = GL_RGB;
if (nrChannels == 4) {
glChannels = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, glChannels, width, height, 0, glChannels, GL_UNSIGNED_BYTE, data);
if (settings.mipmaps) {
glGenerateMipmap(GL_TEXTURE_2D);
}
} else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
render_transparent = settings.transparent;
}
unsigned int id;
bool render_transparent = false;
};
#endif //ECSGAME_TEXTURE_H

View File

@ -28,29 +28,48 @@ public:
shader.setMat4("projection", camera->projection);
shader.setMat4("view", glm::inverse(cameraTransform->matrix));
std::vector<RenderObject> renderObjects;
pWorld->each<Mesh, Transform>([&](Entity *ent, ComponentHandle<Mesh> mesh, ComponentHandle<Transform> transform) {
shader.setMat4("model", transform->matrix);
mesh->render();
renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get()));
});
// TODO: Duplicate of loop above, but for ObjMesh instead of Mesh. Is it possible to do this implicitly via polymorphism?
// TODO: Is it possible to do get ObjMeshes in the Mesh loop above implicitly via polymorphism?
pWorld->each<ObjMesh, Transform>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform) {
shader.setMat4("model", transform->matrix);
mesh->render();
renderObjects.emplace_back(RenderObject(transform->matrix, 0, mesh.get()));
});
// Render ObjMeshes with textures
// ObjMesh with textures
pWorld->each<ObjMesh, Transform, Texture>([&](Entity *ent, ComponentHandle<ObjMesh> mesh, ComponentHandle<Transform> transform, ComponentHandle<Texture> texture) {
shader.setMat4("model", transform->matrix);
glBindTexture(GL_TEXTURE_2D, texture->id);
mesh->render();
renderObjects.emplace_back(RenderObject(transform->matrix, texture->id, mesh.get()));
});
// TODO: Separate lists for transparent and non-transparent RenderObjects. The non-transparent list is
// rendered first, then the transparent list is sorted and rendered.
for (const RenderObject &obj : renderObjects) {
shader.setMat4("model", obj.matrix);
// 0 can't be a valid texture name, so we use it for meshes without textures here
if (obj.texture_id != 0) {
glBindTexture(GL_TEXTURE_2D, obj.texture_id);
}
obj.mesh.render();
}
});
}
struct RenderObject {
RenderObject(const glm::mat4 &matrix, unsigned int textureId, const Mesh &mesh) : matrix(matrix),
texture_id(textureId),
mesh(mesh) {}
glm::mat4 matrix;
unsigned int texture_id;
Mesh mesh;
};
private:
float gravityAmount;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

BIN
Resources/tex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 MiB

View File

@ -2,10 +2,17 @@
out mediump vec4 FragColor;
in mediump vec2 TexCoord;
in mediump vec3 Normal;
uniform sampler2D ourTexture;
uniform sampler2D tex;
void main()
{
FragColor = texture(ourTexture, TexCoord);
mediump vec4 texColor = texture(tex, TexCoord);
// Alpha Scissors
if(texColor.a < 0.1)
discard;
FragColor = texColor;
}

View File

@ -4,6 +4,7 @@ layout (location = 1) in vec3 NORMAL;
layout (location = 2) in vec2 UV;
out vec2 TexCoord;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
@ -13,4 +14,5 @@ void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = UV;
Normal = NORMAL;
}

View File

@ -33,6 +33,7 @@ static void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
}
int main() {
// TODO: Move this to RenderSystem?
GLFWwindow *window;
/* Initialize the library */
@ -65,6 +66,10 @@ int main() {
glEnable(GL_DEPTH_TEST);
// Transparency
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// TODO: Could be automated by getting all classes within 'ECS/Systems'
// world->registerSystem(new GravitySystem(-9.8f));
// world->registerSystem(new PositionDebugOutputSystem());
@ -83,7 +88,7 @@ int main() {
Entity *box2 = world->create();
box2->assign<Transform>();
box2->assign<ObjMesh>("Resources/Monkey.obj");
box2->assign<Texture>("Resources/tex.jpg");
box2->assign<Texture>("Resources/tex.png", Texture::Settings(true, true));
box2->get<Transform>()->translate(glm::vec3(0.0f, 0.0f, -5.0f));
Shader defaultShader("Shaders/default-vertex.vs", "Shaders/default-fragment.fs");