Add renderer stuff

This commit is contained in:
2025-03-06 13:49:52 +03:00
parent d9437c8619
commit dd05797b95
11 changed files with 730 additions and 6 deletions

View File

@@ -44,6 +44,10 @@ void GL_CheckErrorFunction(const char* expression, const char* filename, int lin
Msg( "OpenGL Error: %s (%s) at %s:%i", expression, GL_ErrorString( err ), filename, line );// Msg("OpenGL Error: %s [%s]\n", GL_ErrorString(err), GL_TargetToString(tex->target));
}
void GL_SetTexture( int slot, uint texture )
{
}
uint GetGLBlendFactor(BlendFactor factor)
{
switch (factor)

View File

@@ -13,6 +13,8 @@ void GL_CheckError();
void GL_CheckErrorEx(const char* filename, int line);
void GL_CheckErrorFunction(const char* expression, const char* filename, int line);
void GL_SetTexture( int slot, uint texture );
#define GL_CHECK_ERROR() \
GL_CheckErrorEx(__FILE__, __LINE__)
@@ -20,6 +22,9 @@ void GL_CheckErrorFunction(const char* expression, const char* filename, int lin
expr; \
GL_CheckErrorFunction(#expr, __FILE__, __LINE__)
// OpenGL 1.3 Functional
// OpenGL 1.5 Functional
extern PFNGLGENQUERIESPROC glGenQueries;
extern PFNGLDELETEQUERIESPROC glDeleteQueries;

View File

@@ -57,6 +57,24 @@ enum PrimitiveType
PT_TRIANGLES
};
enum TextureWrap
{
TW_REPEAT,
TW_MIRROREDREPEAT,
TW_CLAMPTOEDGE,
TW_CLAMPTOBORDER
};
enum TextureFilter
{
TF_NEAREST,
TF_LINEAR,
TF_NEARESTMIPMAPNEAREST,
TF_LINEARMIPMAPNEAREST,
TF_NEARESTMIPMAPLINEAR,
TF_LINEARMIPMAPLINEAR
};
// Base structure for render view (view and projection matrices, viewport settings)
struct View
{

View File

@@ -136,11 +136,11 @@ void RenderDevice::SetReadRenderTarget(RenderTarget* renderTarget)
if (renderTarget) {
if (m_activeReadRT != renderTarget) {
m_activeReadRT = renderTarget;
//glBindFramebuffer(GL_READ_FRAMEBUFFER, renderTarget->m_framebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, renderTarget->m_framebuffer);
}
}
else { // set default rt
// glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
}
@@ -149,11 +149,11 @@ void RenderDevice::SetWriteRenderTarget(RenderTarget* renderTarget)
if (renderTarget) {
if (m_activeWriteRT != renderTarget) {
m_activeWriteRT = renderTarget;
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderTarget->m_framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderTarget->m_framebuffer);
}
}
else { // set default rt
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
}

View File

@@ -4,8 +4,6 @@
#include "render/texturesmanager.h"
#include "render/texture2d.h"
#include "glad/glad.h"
void RenderTarget::setDefaultFramebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);

255
engine/render/texture2d.cpp Normal file
View File

@@ -0,0 +1,255 @@
#include <assert.h>
#include "render/texture2d.h"
#include "render/texturesmanager.h"
#include "render/gl_shared.h"
GLint GetGlWrap(TextureWrap wrap);
GLint GetGlTexFilter(TextureFilter filter);
Texture2D* Texture2D::Create()
{
return new Texture2D;
}
Texture2D::Texture2D()
{
m_pf = PF_UNKNOWN;
m_width = 0;
m_height = 0;
m_channels = 0;
m_handle = -1;
}
Texture2D::~Texture2D()
{
m_pf = PF_UNKNOWN;
m_width = 0;
m_height = 0;
m_channels = 0;
m_handle = -1;
}
void Texture2D::CreateBlackTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
byte* data = new byte[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 0;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateWhiteTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
byte* data = new byte[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 255;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateGrayTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
byte* data = new byte[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 255 / 2;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateTexture_Generator(int width, int height, int channels, int color)
{
size_t textureSize = width * height * channels;
byte* data = new byte[textureSize];
assert(data);
m_textureFileName = "$generator_texture$";
for (int i = 0; i < (int)textureSize; i++) {
data[i] = color;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateFromExistedData(void* data, int width, int height, int channels)
{
//assert(data);
m_width = width;
m_height = height;
m_channels = channels;
glGenTextures(1, &m_handle);
glBindTexture(GL_TEXTURE_2D, m_handle);
glTexImage2D(GL_TEXTURE_2D, 0, (channels == 3) ? GL_RGB : GL_RGBA, width, height, 0, (channels == 3) ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture2D::CreateRaw(void* data, int width, int height, PixelFormat pf)
{
m_width = width;
m_height = height;
m_channels = (pf == PF_R8G8B8) ? 3 : 4;
m_pf = pf;
glGenTextures(1, &m_handle);
glBindTexture(GL_TEXTURE_2D, m_handle);
glTexImage2D(GL_TEXTURE_2D, 0, getGLInternalPF(pf), width, height, 0, getGLInternalPF(pf), GL_UNSIGNED_BYTE, data);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
void Texture2D::GenerateMipmaps()
{
glBindTexture(GL_TEXTURE_2D, m_handle);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//if (g_texAnisoFilter.getValueB()) {
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, g_texAnisoLevel.getValueI());
//}
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture2D::Bind()
{
glBindTexture(GL_TEXTURE_2D, m_handle);
}
void Texture2D::SetWrapS(TextureWrap wrap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGlWrap(wrap));
}
void Texture2D::SetWrapT(TextureWrap wrap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGlWrap(wrap));
}
void Texture2D::SetMin(TextureFilter filter)
{
GLint param = 0;
param = getGlTexFilter(filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
}
void Texture2D::SetMag(TextureFilter filter)
{
GLint param = 0;
param = getGlTexFilter(filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
GLint GetGlWrap(TextureWrap wrap)
{
GLint param = 0;
if (wrap == TextureWrap::Repeat)
param = GL_REPEAT;
else if (wrap == TextureWrap::MirroredRepeat)
param = GL_MIRRORED_REPEAT;
else if (wrap == TextureWrap::ClampToEdge)
param = GL_CLAMP_TO_EDGE;
else if (wrap == TextureWrap::ClampToBorder)
param = GL_CLAMP_TO_BORDER;
return param;
}
GLint GetGlTexFilter(TextureFilter filter)
{
GLint param = 0;
if (filter == TextureFilter::Linear)
param = GL_LINEAR;
else if (filter == TextureFilter::Nearest)
param = GL_NEAREST;
else if (filter == TextureFilter::LinearMipmapLinear)
param = GL_LINEAR_MIPMAP_LINEAR;
else if (filter == TextureFilter::LinearMipmapNearest)
param = GL_LINEAR_MIPMAP_NEAREST;
else if (filter == TextureFilter::NearestMipmapLinear)
param = GL_NEAREST_MIPMAP_LINEAR;
else if (filter == TextureFilter::NearestMipmapNearest)
param = GL_NEAREST_MIPMAP_NEAREST;
return param;
}
uint getGLPF(PixelFormat pf)
{
return 0;
//return uint32_t();
}
// Kirill: Remove to render_main.cpp or something else
uint getGLInternalPF(PixelFormat pf)
{
switch (pf)
{
case PF_UNKNOWN:
return 0;
case PF_R8G8B8:
case PF_R8G8B8F:
return GL_RGB;
case PF_R8G8B8A8:
case PF_R8G8B8A8F:
return GL_RGBA;
}
return 0;
}
uint getGLTypePF(PixelFormat pf)
{
switch (pf)
{
case PF_UNKNOWN:
return 0;
case PF_R8G8B8:
case PF_R8G8B8A8:
return GL_UNSIGNED_BYTE;
case PF_R8G8B8F:
case PF_R8G8B8A8F:
return GL_FLOAT;
}
return 0;
}

49
engine/render/texture2d.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef TEXTURE2D_H
#define TEXTURE2D_H
#include <string>
#include "render/render_shared.h"
class TexturesManager;
class Texture2D
{
friend class TexturesManager;
public:
static Texture2D* Create();
public:
Texture2D();
~Texture2D();
void CreateBlackTexture(int width, int height, int channels);
void CreateWhiteTexture(int width, int height, int channels);
void CreateGrayTexture(int width, int height, int channels);
void CreateTexture_Generator(int width, int height, int channels, int color);
void CreateFromExistedData(void* data, int width, int height, int channels);
void CreateFromFile(const char* filename);
void CreateRaw(void* data, int width, int height, PixelFormat pf);
void GenerateMipmaps();
void Bind();
void SetWrapS(TextureWrap wrap);
void SetWrapT(TextureWrap wrap);
void SetMin(TextureFilter filter);
void SetMag(TextureFilter filter);
uint GetHandle() { return m_handle; }
private:
std::string m_textureFileName;
PixelFormat m_pf;
int m_width;
int m_height;
int m_channels;
uint m_handle;
};
#endif // !TEXTURE2D_H

View File

@@ -0,0 +1,192 @@
#include "utils/logger.h"
#include "filesystem/filemanager.h"
#include "render/texture2d.h"
#include "render/texturesmanager.h"
#include "render/gl_shared.h"
// STB Image loading code
void Texture2D::CreateFromFile(const char* filename)
{
/*
int width, height, channels;
m_textureFileName = filename;
File* file = g_fileManager->OpenFile(filename, FileAccess::Read);
file->seek(SeekDir::End, 0);
size_t imageSize = file->tell();
file->seek(SeekDir::Begin, 0);
uint8_t* fileData = (uint8_t*)malloc(imageSize);
file->read(fileData, imageSize);
g_fileManager->CloseFile(file);
uint8_t* imageData = stbi_load_from_memory(fileData, int(imageSize), &width, &height, &channels, 0);
if (imageData == NULL) {
free(fileData);
Msg("Texture loading error: %s (%s)", filename, stbi_failure_reason());
assert(imageData);
}
CreateFromExistedData(imageData, width, height, channels);
m_textureFileName = filename;
free(fileData);
stbi_image_free(imageData);
*/
}
static const char* g_texFileExtensions[] = { ".png", ".jpeg", ".jpg", ".tga", ".bmp" };
const int kTexFileExtensionsSize = sizeof(g_texFileExtensions) / sizeof(g_texFileExtensions[0]);
TexturesManager* g_texturesManager = NULL;
TexturesManager::TexturesManager()
{
m_notex = NULL;
}
TexturesManager::~TexturesManager()
{
}
void TexturesManager::Init()
{
//stbi_set_flip_vertically_on_load(true);
m_notex = LoadTexture2D("content/textures/system/notex.png", true);
if (!m_notex) {
Logger::Error("TexturesManager::Init: Failed to initialize system texture! 'system/notex.png' is not exist.");
}
}
void TexturesManager::Shutdown()
{
if (!m_textures.empty()) {
Msg("--- unfreed textures ---");
for (std::vector<Texture2D*>::iterator it = m_textures.begin(); it != m_textures.end(); ++it) {
Msg("%s", (*it)->m_textureFileName.c_str());
delete* it;
*it = NULL;
}
m_textures.clear();
}
}
void TexturesManager::SetTexture(int slot, Texture2D* texture)
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, texture ? texture->GetHandle() : 0);
}
Texture2D* TexturesManager::CreateManual2D(const char* name, int width, int height, PixelFormat format, bool useAsRenderTarget)
{
for (std::vector<Texture2D*>::iterator it = m_textures.begin(); it != m_textures.end(); ++it) {
if ((*it)->m_textureFileName == name) {
Logger::Error("TexturesManager::CreateManual2D: texture %s is already created!", name);
}
}
// allocate
Texture2D* texture = Texture2D::Create();
texture->CreateRaw(nullptr, width, height, format);
texture->m_textureFileName = name;
if (useAsRenderTarget)
Msg("Created rt texture [%s]", name);
return texture;
}
bool IsSupportedExtension(const char* filename)
{
std::string ext = fs::getFileExtension(filename);
for (int i = 0; i < kTexFileExtensionsSize; i++) {
if (ext == g_texFileExtensions[i]) {
return true;
}
}
return false;
}
Texture2D* TexturesManager::LoadTexture2D(const char* texturename, bool useMipmaps /*= false*/)
{
int texturesNbr = m_textures.size();
for (int i = 0; i < texturesNbr; i++) {
if (m_textures[i]->m_textureFileName == texturename)
return m_textures[i];
}
if (strcmp(texturename, "$white$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$white$";
tex->CreateWhiteTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$black$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$black$";
tex->CreateBlackTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$gray$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$gray$";
tex->CreateGrayTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$gray_console$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->CreateTexture_Generator(16, 16, 3, 32);
m_textures.push_back(tex);
return tex;
}
if (strlen(texturename) <= 0) {
return m_notex;
}
std::string texnamebuf;
// find texture from disk
for (int i = 0; i < kTexFileExtensionsSize; i++)
{
std::string textureFilename = fs::getFileNameWithoutExtension(texturename);
textureFilename += g_texFileExtensions[i];
if (g_fileManager->FileExist(textureFilename.c_str()))
{
texnamebuf = textureFilename;
break;
}
}
if (!texnamebuf.empty()) {
Texture2D* texture = Texture2D::Create();
texture->CreateFromFile(texnamebuf.c_str());
if (useMipmaps)
texture->GenerateMipmaps();
Msg("loaded %s", fs::getFilenameWithoutPathAndExtension(texturename).c_str());
m_textures.push_back(texture);
return texture;
}
else if (texnamebuf.empty() && m_notex) {
Msg("not found %s", fs::getFilenameWithoutPathAndExtension(texturename).c_str());
return m_notex;
}
return NULL;
}

View File

@@ -0,0 +1,38 @@
#ifndef TEXTURESMANAGER_H
#define TEXTURESMANAGER_H
#include <vector>
#include "render/render_shared.h"
class Texture2D;
class TexturesManager
{
public:
TexturesManager();
~TexturesManager();
void Init();
void Shutdown();
void SetTexture(int slot, Texture2D* texture);
Texture2D* CreateManual2D(
const char* name,
int width,
int height,
PixelFormat format,
bool useAsRenderTarget = false);
Texture2D* LoadTexture2D(const char* texturename, bool useMipmaps = false);
private:
std::vector<Texture2D*> m_textures;
Texture2D* m_notex;
};
extern TexturesManager* g_texturesManager;
#endif // !TEXTURESMANAGER_H