Hello! I need some help!
I have written sprite batching for my engine. But textures dont appear on the screen. Instead I can see only white squares. Can you solve the problem, pls?
There are my shaders and source code of sprite batching:
Vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0);
ourColor = color;
TexCoord = texCoord;
}
Fragment shader:
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
vec2 _texCoord = vec2(TexCoord.x, -TexCoord.y);
color = texture(ourTexture, _texCoord);
}
SpriteBatch.h:
#pragma once
#include "ShaderProgram.h"
#include "Vertex.h"
#include "TextureManager.h"
#include <GL/glew.h>
#include <vector>
class Rect
{
public:
GLfloat x, y, z, w, h;
};
class SpriteBatch
{
class RenderBatch
{
public:
GLuint offset;
GLuint numSprites;
GLuint textureID;
RenderBatch() : offset(0), numSprites(0), textureID(0) {}
RenderBatch(GLuint Offset, GLuint NumSprites, GLuint TextureID) : offset(Offset), numSprites(NumSprites), textureID(TextureID) {}
};
private:
GLuint _vao;
GLuint _vbo;
GLuint _ebo;
size_t _sizeOfBuffers;
size_t _numSprites;
size_t _batchIterator;
std::vector<Vertex> _vertices;
std::vector<GLuint> _indices;
std::vector<RenderBatch> _spriteBatch;
public:
SpriteBatch();
void init(size_t sizeOfBuffers = 5);
void draw(const Rect& dstRect, const Rect& srcRect, const Texture& texture, const Color& color = { 1.0f, 1.0f, 1.0f });
void render();
};
SpriteBatch.cpp:
#include "SpriteBatch.h"
#include <iostream>
#include "DebugInfo.h"
/* TODO : */
/*
sort it by z-value or use pojection
*/
SpriteBatch::SpriteBatch() :
_vertices(0),
_indices(0),
_spriteBatch(1),
_numSprites(0),
_sizeOfBuffers(0),
_batchIterator(0),
_vao(0),
_vbo(0),
_ebo(0)
{
_spriteBatch[0].textureID = 0;
}
void SpriteBatch::init(size_t sizeOfBuffers)
{
glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ebo);
glBindVertexArray(_vao);
_sizeOfBuffers = sizeOfBuffers;
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeOfBuffers * 4 * sizeof(Vertex), nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfBuffers * 6 * sizeof(GLuint), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
}
void SpriteBatch::draw(const Rect& dstRect, const Rect& srcRect, const Texture& texture, const Color& color)
{
if (_spriteBatch[_batchIterator].textureID != texture.textureID)
{
if (_batchIterator + 1 == _spriteBatch.size())
_spriteBatch.emplace_back(_spriteBatch[_batchIterator].offset + _spriteBatch[_batchIterator].numSprites, 1, texture.textureID);
++_batchIterator;
}
else
{
_spriteBatch[_batchIterator].numSprites++;
}
if (_numSprites * 4 >= _vertices.size())
{
_vertices.resize(_vertices.size() + 4);
_indices.resize(_indices.size() + 6);
}
// TOP RIGHT
_vertices[_numSprites * 4].position = { dstRect.x + dstRect.w, dstRect.y, dstRect.z };
_vertices[_numSprites * 4].color = color;
_vertices[_numSprites * 4].uv = { srcRect.x + srcRect.w, srcRect.y };
// BOT RIGHT
_vertices[_numSprites * 4 + 1].position = { dstRect.x + dstRect.w, dstRect.y - dstRect.h, dstRect.z };
_vertices[_numSprites * 4 + 1].color = color;
_vertices[_numSprites * 4 + 1].uv = { srcRect.x + srcRect.w, srcRect.y + srcRect.h };
// BOT LEFT
_vertices[_numSprites * 4 + 2].position = { dstRect.x, dstRect.y - dstRect.h, dstRect.z };
_vertices[_numSprites * 4 + 2].color = color;
_vertices[_numSprites * 4 + 2].uv = { srcRect.x, srcRect.y + srcRect.h };
// TOP LEFT
_vertices[_numSprites * 4 + 3].position = { dstRect.x, dstRect.y, dstRect.z };
_vertices[_numSprites * 4 + 3].color = color;
_vertices[_numSprites * 4 + 3].uv = { srcRect.x, srcRect.y };
_indices[_numSprites * 6] = _numSprites * 4;
_indices[_numSprites * 6 + 1] = _numSprites * 4 + 1;
_indices[_numSprites * 6 + 2] = _numSprites * 4 + 3;
_indices[_numSprites * 6 + 3] = _numSprites * 4 + 1;
_indices[_numSprites * 6 + 4] = _numSprites * 4 + 2;
_indices[_numSprites * 6 + 5] = _numSprites * 4 + 3;
++_numSprites;
}
void SpriteBatch::render()
{
glBindVertexArray(_vao);
glBufferSubData(GL_ARRAY_BUFFER, 0, _numSprites * 4 * sizeof(Vertex), _vertices.data());
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, _numSprites * 6 * sizeof(GLuint), _indices.data());
#ifdef DEBUG
#define DELAY_TIME 5000
static Uint32 lastTick = SDL_GetTicks();
if (SDL_GetTicks() - lastTick > DELAY_TIME && _vertices.size() / 4 > _sizeOfBuffers)
{
DebugInfo::printWarning("Not enough memory in GPU");
lastTick = SDL_GetTicks();
}
#endif // DEBUG
for (size_t i = 1; i <= _batchIterator; ++i)
{
glBindTexture(GL_TEXTURE_2D, _spriteBatch[i].textureID);
glDrawElements(GL_TRIANGLES, _spriteBatch[i].numSprites * 6, GL_UNSIGNED_INT, (GLvoid*)(_spriteBatch[i].offset * 6 * sizeof(GLuint)));
}
_batchIterator = 0;
_numSprites = 0;
glBindVertexArray(0);
}