feat(渲染器): 添加基础着色器文件并重构形状和精灵渲染器
重构形状渲染器和精灵渲染器,移除内置着色器代码改为使用外部着色器文件 添加基础着色器文件包括形状、精灵、文本和MSDF字体渲染所需着色器 渲染器现在必须设置材质才能工作,提供更灵活的着色器定制能力
This commit is contained in:
parent
70c2806c77
commit
5158fd713e
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <extra2d/render/render_types.h>
|
|
||||||
#include <extra2d/render/render_device.h>
|
|
||||||
#include <extra2d/render/buffer.h>
|
#include <extra2d/render/buffer.h>
|
||||||
|
#include <extra2d/render/material.h>
|
||||||
|
#include <extra2d/render/render_context.h>
|
||||||
#include <extra2d/render/vao.h>
|
#include <extra2d/render/vao.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <glm/mat4x4.hpp>
|
#include <glm/mat4x4.hpp>
|
||||||
|
|
@ -23,7 +23,8 @@ struct ShapeVertex {
|
||||||
/**
|
/**
|
||||||
* @brief 图形渲染器
|
* @brief 图形渲染器
|
||||||
*
|
*
|
||||||
* 支持矩形、圆形、线条等基本图形的批量渲染
|
* 支持矩形、圆形、线条等基本图形的批量渲染。
|
||||||
|
* 必须设置 Material 才能渲染。
|
||||||
*/
|
*/
|
||||||
class ShapeRenderer {
|
class ShapeRenderer {
|
||||||
public:
|
public:
|
||||||
|
|
@ -43,6 +44,18 @@ public:
|
||||||
*/
|
*/
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置材质(必须设置才能渲染)
|
||||||
|
* @param material 材质模板
|
||||||
|
*/
|
||||||
|
void setMaterial(Ref<Material> material) { material_ = material; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取材质
|
||||||
|
* @return 材质模板
|
||||||
|
*/
|
||||||
|
Ref<Material> material() const { return material_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 开始批量渲染
|
* @brief 开始批量渲染
|
||||||
*/
|
*/
|
||||||
|
|
@ -104,14 +117,11 @@ private:
|
||||||
Array<ShapeVertex> vertices_;
|
Array<ShapeVertex> vertices_;
|
||||||
size_t vertexCount_ = 0;
|
size_t vertexCount_ = 0;
|
||||||
|
|
||||||
GLuint fillShader_ = 0;
|
|
||||||
GLuint lineShader_ = 0;
|
|
||||||
glm::mat4 viewProjection_;
|
glm::mat4 viewProjection_;
|
||||||
|
Ref<Material> material_;
|
||||||
uint32 drawCalls_ = 0;
|
|
||||||
float currentLineWidth_ = 1.0f;
|
float currentLineWidth_ = 1.0f;
|
||||||
|
uint32 drawCalls_ = 0;
|
||||||
|
|
||||||
bool createShaders();
|
|
||||||
void flush(GLenum mode);
|
void flush(GLenum mode);
|
||||||
void addVertex(float x, float y, const glm::vec4& color);
|
void addVertex(float x, float y, const glm::vec4& color);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ struct SpriteData {
|
||||||
/**
|
/**
|
||||||
* @brief 精灵渲染器
|
* @brief 精灵渲染器
|
||||||
*
|
*
|
||||||
* 高性能批量精灵渲染器,支持 Material 系统
|
* 高性能批量精灵渲染器,支持 Material 系统。
|
||||||
|
* 必须设置 Material 才能渲染。
|
||||||
*/
|
*/
|
||||||
class SpriteRenderer {
|
class SpriteRenderer {
|
||||||
public:
|
public:
|
||||||
|
|
@ -64,7 +65,7 @@ public:
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置材质
|
* @brief 设置材质(必须设置才能渲染)
|
||||||
* @param material 材质模板
|
* @param material 材质模板
|
||||||
*/
|
*/
|
||||||
void setMaterial(Ref<Material> material) { material_ = material; }
|
void setMaterial(Ref<Material> material) { material_ = material; }
|
||||||
|
|
@ -80,20 +81,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void begin(const glm::mat4 &viewProjection);
|
void begin(const glm::mat4 &viewProjection);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 绘制精灵(使用默认材质)
|
|
||||||
* @param texture 纹理 ID
|
|
||||||
* @param data 精灵数据
|
|
||||||
*/
|
|
||||||
void draw(GLuint texture, const SpriteData &data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制精灵(使用材质实例)
|
* @brief 绘制精灵(使用材质实例)
|
||||||
* @param texture 纹理 ID
|
* @param texture 纹理 ID
|
||||||
* @param data 精灵数据
|
* @param data 精灵数据
|
||||||
* @param instance 材质实例
|
* @param instance 材质实例(nullptr 则使用默认材质)
|
||||||
*/
|
*/
|
||||||
void draw(GLuint texture, const SpriteData &data, MaterialInstance *instance);
|
void draw(GLuint texture, const SpriteData &data,
|
||||||
|
MaterialInstance *instance = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 绘制精灵(使用属性块)
|
* @brief 绘制精灵(使用属性块)
|
||||||
|
|
@ -123,7 +118,6 @@ private:
|
||||||
Array<SpriteVertex> vertices_;
|
Array<SpriteVertex> vertices_;
|
||||||
size_t vertexCount_ = 0;
|
size_t vertexCount_ = 0;
|
||||||
|
|
||||||
GLuint shader_ = 0;
|
|
||||||
GLuint currentTexture_ = 0;
|
GLuint currentTexture_ = 0;
|
||||||
glm::mat4 viewProjection_;
|
glm::mat4 viewProjection_;
|
||||||
|
|
||||||
|
|
@ -133,9 +127,7 @@ private:
|
||||||
uint32 drawCalls_ = 0;
|
uint32 drawCalls_ = 0;
|
||||||
uint32 spriteCount_ = 0;
|
uint32 spriteCount_ = 0;
|
||||||
|
|
||||||
bool createShader();
|
|
||||||
void flush();
|
void flush();
|
||||||
void flushWithMaterial();
|
|
||||||
void addQuad(const SpriteData &data, GLuint texture);
|
void addQuad(const SpriteData &data, GLuint texture);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#version 450 core
|
||||||
|
in vec2 v_texCoord;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform float u_pxRange;
|
||||||
|
uniform vec4 u_color;
|
||||||
|
uniform float u_outlineWidth;
|
||||||
|
uniform vec4 u_outlineColor;
|
||||||
|
uniform vec2 u_shadowOffset;
|
||||||
|
uniform vec4 u_shadowColor;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
float median(float r, float g, float b) {
|
||||||
|
return max(min(r, g), min(max(r, g), b));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 msdf = texture(u_texture, v_texCoord).rgb;
|
||||||
|
float sigDist = median(msdf.r, msdf.g, msdf.b);
|
||||||
|
|
||||||
|
float pxRange = u_pxRange;
|
||||||
|
float alpha = smoothstep(0.5 - 0.5/pxRange, 0.5 + 0.5/pxRange, sigDist);
|
||||||
|
|
||||||
|
float outlineAlpha = 0.0;
|
||||||
|
if (u_outlineWidth > 0.0) {
|
||||||
|
outlineAlpha = smoothstep(
|
||||||
|
0.5 - u_outlineWidth - 0.5/pxRange,
|
||||||
|
0.5 - u_outlineWidth + 0.5/pxRange,
|
||||||
|
sigDist
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadowAlpha = 0.0;
|
||||||
|
if (u_shadowOffset != vec2(0.0)) {
|
||||||
|
vec3 shadowMsdf = texture(u_texture, v_texCoord - u_shadowOffset).rgb;
|
||||||
|
float shadowDist = median(shadowMsdf.r, shadowMsdf.g, shadowMsdf.b);
|
||||||
|
shadowAlpha = smoothstep(0.5 - 0.5/pxRange, 0.5 + 0.5/pxRange, shadowDist);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 color = vec4(0.0);
|
||||||
|
|
||||||
|
if (shadowAlpha > 0.0) {
|
||||||
|
color = mix(color, u_shadowColor, shadowAlpha * u_shadowColor.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outlineAlpha > 0.0) {
|
||||||
|
color = mix(color, u_outlineColor, outlineAlpha * u_outlineColor.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
color = mix(color, u_color, alpha * u_color.a);
|
||||||
|
|
||||||
|
fragColor = color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"name": "msdf_font",
|
||||||
|
"vertex": "msdf_font.vert",
|
||||||
|
"fragment": "msdf_font.frag",
|
||||||
|
"properties": {
|
||||||
|
"u_texture": {
|
||||||
|
"type": "sampler2D",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"u_color": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [1.0, 1.0, 1.0, 1.0]
|
||||||
|
},
|
||||||
|
"u_pxRange": {
|
||||||
|
"type": "float",
|
||||||
|
"default": 4.0
|
||||||
|
},
|
||||||
|
"u_outlineWidth": {
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.0
|
||||||
|
},
|
||||||
|
"u_outlineColor": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [0.0, 0.0, 0.0, 1.0]
|
||||||
|
},
|
||||||
|
"u_shadowOffset": {
|
||||||
|
"type": "vec2",
|
||||||
|
"default": [0.0, 0.0]
|
||||||
|
},
|
||||||
|
"u_shadowColor": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [0.0, 0.0, 0.0, 0.5]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"blend": {
|
||||||
|
"enabled": true,
|
||||||
|
"src": "SRC_ALPHA",
|
||||||
|
"dst": "ONE_MINUS_SRC_ALPHA"
|
||||||
|
},
|
||||||
|
"depth": {
|
||||||
|
"enabled": false,
|
||||||
|
"write": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) in vec2 a_position;
|
||||||
|
layout(location = 1) in vec2 a_texCoord;
|
||||||
|
|
||||||
|
uniform mat4 u_projection;
|
||||||
|
|
||||||
|
out vec2 v_texCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_projection * vec4(a_position, 0.0, 1.0);
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#version 450 core
|
||||||
|
in vec4 v_color;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = v_color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "shape_default",
|
||||||
|
"vertex": "shape.vert",
|
||||||
|
"fragment": "shape.frag",
|
||||||
|
"properties": {
|
||||||
|
"u_color": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [1.0, 1.0, 1.0, 1.0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"blend": {
|
||||||
|
"enabled": true,
|
||||||
|
"src": "SRC_ALPHA",
|
||||||
|
"dst": "ONE_MINUS_SRC_ALPHA"
|
||||||
|
},
|
||||||
|
"depth": {
|
||||||
|
"enabled": false,
|
||||||
|
"write": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) in vec2 a_position;
|
||||||
|
layout(location = 1) in vec4 a_color;
|
||||||
|
|
||||||
|
uniform mat4 u_viewProjection;
|
||||||
|
|
||||||
|
out vec4 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0);
|
||||||
|
v_color = a_color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#version 450 core
|
||||||
|
in vec2 v_texCoord;
|
||||||
|
in vec4 v_color;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = texture(u_texture, v_texCoord) * v_color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "sprite_default",
|
||||||
|
"vertex": "sprite.vert",
|
||||||
|
"fragment": "sprite.frag",
|
||||||
|
"properties": {
|
||||||
|
"u_texture": {
|
||||||
|
"type": "sampler2D",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"u_color": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [1.0, 1.0, 1.0, 1.0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"blend": {
|
||||||
|
"enabled": true,
|
||||||
|
"src": "SRC_ALPHA",
|
||||||
|
"dst": "ONE_MINUS_SRC_ALPHA"
|
||||||
|
},
|
||||||
|
"depth": {
|
||||||
|
"enabled": false,
|
||||||
|
"write": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) in vec2 a_position;
|
||||||
|
layout(location = 1) in vec2 a_texCoord;
|
||||||
|
layout(location = 2) in vec4 a_color;
|
||||||
|
|
||||||
|
uniform mat4 u_viewProjection;
|
||||||
|
|
||||||
|
out vec2 v_texCoord;
|
||||||
|
out vec4 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0);
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
v_color = a_color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#version 450 core
|
||||||
|
in vec2 v_texCoord;
|
||||||
|
in vec4 v_color;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float alpha = texture(u_texture, v_texCoord).r;
|
||||||
|
fragColor = vec4(v_color.rgb, v_color.a * alpha);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "text_default",
|
||||||
|
"vertex": "text.vert",
|
||||||
|
"fragment": "text.frag",
|
||||||
|
"properties": {
|
||||||
|
"u_texture": {
|
||||||
|
"type": "sampler2D",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"u_color": {
|
||||||
|
"type": "vec4",
|
||||||
|
"default": [1.0, 1.0, 1.0, 1.0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"blend": {
|
||||||
|
"enabled": true,
|
||||||
|
"src": "SRC_ALPHA",
|
||||||
|
"dst": "ONE_MINUS_SRC_ALPHA"
|
||||||
|
},
|
||||||
|
"depth": {
|
||||||
|
"enabled": false,
|
||||||
|
"write": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) in vec2 a_position;
|
||||||
|
layout(location = 1) in vec2 a_texCoord;
|
||||||
|
layout(location = 2) in vec4 a_color;
|
||||||
|
|
||||||
|
uniform mat4 u_projection;
|
||||||
|
|
||||||
|
out vec2 v_texCoord;
|
||||||
|
out vec4 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_projection * vec4(a_position, 0.0, 1.0);
|
||||||
|
v_texCoord = a_texCoord;
|
||||||
|
v_color = a_color;
|
||||||
|
}
|
||||||
|
|
@ -5,32 +5,6 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
static const char* SHAPE_VERTEX_SHADER = R"(
|
|
||||||
#version 450 core
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec4 a_color;
|
|
||||||
|
|
||||||
uniform mat4 u_viewProjection;
|
|
||||||
|
|
||||||
out vec4 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0);
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char* SHAPE_FRAGMENT_SHADER = R"(
|
|
||||||
#version 450 core
|
|
||||||
in vec4 v_color;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = v_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
ShapeRenderer::ShapeRenderer() {
|
ShapeRenderer::ShapeRenderer() {
|
||||||
vertices_.resize(MAX_VERTICES);
|
vertices_.resize(MAX_VERTICES);
|
||||||
}
|
}
|
||||||
|
|
@ -57,22 +31,13 @@ bool ShapeRenderer::init() {
|
||||||
vao_->setFormat(format);
|
vao_->setFormat(format);
|
||||||
vao_->bindVertexBuffer(0, *vbo_, 0, sizeof(ShapeVertex));
|
vao_->bindVertexBuffer(0, *vbo_, 0, sizeof(ShapeVertex));
|
||||||
|
|
||||||
if (!createShaders()) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeRenderer::shutdown() {
|
void ShapeRenderer::shutdown() {
|
||||||
if (fillShader_) {
|
|
||||||
glDeleteProgram(fillShader_);
|
|
||||||
fillShader_ = 0;
|
|
||||||
}
|
|
||||||
if (lineShader_) {
|
|
||||||
glDeleteProgram(lineShader_);
|
|
||||||
lineShader_ = 0;
|
|
||||||
}
|
|
||||||
vao_.reset();
|
vao_.reset();
|
||||||
vbo_.reset();
|
vbo_.reset();
|
||||||
|
material_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeRenderer::begin(const glm::mat4& viewProjection) {
|
void ShapeRenderer::begin(const glm::mat4& viewProjection) {
|
||||||
|
|
@ -224,52 +189,20 @@ void ShapeRenderer::end() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShapeRenderer::createShaders() {
|
|
||||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
glShaderSource(vs, 1, &SHAPE_VERTEX_SHADER, nullptr);
|
|
||||||
glCompileShader(vs);
|
|
||||||
|
|
||||||
GLint success;
|
|
||||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glDeleteShader(vs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(fs, 1, &SHAPE_FRAGMENT_SHADER, nullptr);
|
|
||||||
glCompileShader(fs);
|
|
||||||
|
|
||||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glDeleteShader(vs);
|
|
||||||
glDeleteShader(fs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fillShader_ = glCreateProgram();
|
|
||||||
glAttachShader(fillShader_, vs);
|
|
||||||
glAttachShader(fillShader_, fs);
|
|
||||||
glLinkProgram(fillShader_);
|
|
||||||
|
|
||||||
glGetProgramiv(fillShader_, GL_LINK_STATUS, &success);
|
|
||||||
|
|
||||||
lineShader_ = fillShader_;
|
|
||||||
|
|
||||||
glDeleteShader(vs);
|
|
||||||
glDeleteShader(fs);
|
|
||||||
|
|
||||||
return success == GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShapeRenderer::flush(GLenum mode) {
|
void ShapeRenderer::flush(GLenum mode) {
|
||||||
if (vertexCount_ == 0) return;
|
if (vertexCount_ == 0 || !material_) return;
|
||||||
|
|
||||||
vbo_->update(0, vertexCount_ * sizeof(ShapeVertex), vertices_.data());
|
vbo_->update(0, vertexCount_ * sizeof(ShapeVertex), vertices_.data());
|
||||||
|
|
||||||
glUseProgram(fillShader_);
|
material_->apply();
|
||||||
GLint vpLoc = glGetUniformLocation(fillShader_, "u_viewProjection");
|
|
||||||
|
ShaderAsset* shader = material_->shader();
|
||||||
|
if (shader) {
|
||||||
|
GLint vpLoc = shader->getUniformLocation("u_viewProjection");
|
||||||
|
if (vpLoc >= 0) {
|
||||||
glUniformMatrix4fv(vpLoc, 1, GL_FALSE, &viewProjection_[0][0]);
|
glUniformMatrix4fv(vpLoc, 1, GL_FALSE, &viewProjection_[0][0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vao_->bind();
|
vao_->bind();
|
||||||
glDrawArrays(mode, 0, static_cast<GLsizei>(vertexCount_));
|
glDrawArrays(mode, 0, static_cast<GLsizei>(vertexCount_));
|
||||||
|
|
|
||||||
|
|
@ -2,42 +2,9 @@
|
||||||
#include <extra2d/render/render_device.h>
|
#include <extra2d/render/render_device.h>
|
||||||
#include <extra2d/render/render_stats.h>
|
#include <extra2d/render/render_stats.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
static const char* SPRITE_VERTEX_SHADER = R"(
|
|
||||||
#version 450 core
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec2 a_texCoord;
|
|
||||||
layout(location = 2) in vec4 a_color;
|
|
||||||
|
|
||||||
uniform mat4 u_viewProjection;
|
|
||||||
|
|
||||||
out vec2 v_texCoord;
|
|
||||||
out vec4 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0);
|
|
||||||
v_texCoord = a_texCoord;
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char* SPRITE_FRAGMENT_SHADER = R"(
|
|
||||||
#version 450 core
|
|
||||||
in vec2 v_texCoord;
|
|
||||||
in vec4 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = texture(u_texture, v_texCoord) * v_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
SpriteRenderer::SpriteRenderer() {
|
SpriteRenderer::SpriteRenderer() {
|
||||||
vertices_.resize(MAX_VERTICES);
|
vertices_.resize(MAX_VERTICES);
|
||||||
}
|
}
|
||||||
|
|
@ -81,16 +48,10 @@ bool SpriteRenderer::init() {
|
||||||
vao_->bindVertexBuffer(0, *vbo_, 0, sizeof(SpriteVertex));
|
vao_->bindVertexBuffer(0, *vbo_, 0, sizeof(SpriteVertex));
|
||||||
vao_->bindIndexBuffer(*ibo_);
|
vao_->bindIndexBuffer(*ibo_);
|
||||||
|
|
||||||
if (!createShader()) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteRenderer::shutdown() {
|
void SpriteRenderer::shutdown() {
|
||||||
if (shader_) {
|
|
||||||
glDeleteProgram(shader_);
|
|
||||||
shader_ = 0;
|
|
||||||
}
|
|
||||||
vao_.reset();
|
vao_.reset();
|
||||||
vbo_.reset();
|
vbo_.reset();
|
||||||
ibo_.reset();
|
ibo_.reset();
|
||||||
|
|
@ -106,32 +67,23 @@ void SpriteRenderer::begin(const glm::mat4& viewProjection) {
|
||||||
spriteCount_ = 0;
|
spriteCount_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteRenderer::draw(GLuint texture, const SpriteData& data) {
|
|
||||||
if (texture != currentTexture_ || vertexCount_ + VERTICES_PER_SPRITE > MAX_VERTICES) {
|
|
||||||
flush();
|
|
||||||
currentTexture_ = texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
addQuad(data, texture);
|
|
||||||
spriteCount_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteRenderer::draw(GLuint texture, const SpriteData& data, MaterialInstance* instance) {
|
void SpriteRenderer::draw(GLuint texture, const SpriteData& data, MaterialInstance* instance) {
|
||||||
if (material_ && instance) {
|
if (!material_) return;
|
||||||
|
|
||||||
if (instance != currentInstance_ || texture != currentTexture_ ||
|
if (instance != currentInstance_ || texture != currentTexture_ ||
|
||||||
vertexCount_ + VERTICES_PER_SPRITE > MAX_VERTICES) {
|
vertexCount_ + VERTICES_PER_SPRITE > MAX_VERTICES) {
|
||||||
flushWithMaterial();
|
flush();
|
||||||
currentInstance_ = instance;
|
currentInstance_ = instance;
|
||||||
currentTexture_ = texture;
|
currentTexture_ = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
addQuad(data, texture);
|
addQuad(data, texture);
|
||||||
spriteCount_++;
|
spriteCount_++;
|
||||||
} else {
|
|
||||||
draw(texture, data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteRenderer::draw(GLuint texture, const SpriteData& data, const MaterialPropertyBlock& block) {
|
void SpriteRenderer::draw(GLuint texture, const SpriteData& data, const MaterialPropertyBlock& block) {
|
||||||
|
if (!material_) return;
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
currentTexture_ = texture;
|
currentTexture_ = texture;
|
||||||
addQuad(data, texture);
|
addQuad(data, texture);
|
||||||
|
|
@ -139,106 +91,31 @@ void SpriteRenderer::draw(GLuint texture, const SpriteData& data, const Material
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
if (material_ && material_->shader()) {
|
if (material_->shader()) {
|
||||||
material_->shader()->bind();
|
material_->shader()->bind();
|
||||||
block.apply(material_->shader());
|
block.apply(material_->shader());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteRenderer::end() {
|
void SpriteRenderer::end() {
|
||||||
if (material_ && currentInstance_) {
|
|
||||||
flushWithMaterial();
|
|
||||||
} else {
|
|
||||||
flush();
|
flush();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SpriteRenderer::createShader() {
|
|
||||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
glShaderSource(vs, 1, &SPRITE_VERTEX_SHADER, nullptr);
|
|
||||||
glCompileShader(vs);
|
|
||||||
|
|
||||||
GLint success;
|
|
||||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glDeleteShader(vs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(fs, 1, &SPRITE_FRAGMENT_SHADER, nullptr);
|
|
||||||
glCompileShader(fs);
|
|
||||||
|
|
||||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &success);
|
|
||||||
if (!success) {
|
|
||||||
glDeleteShader(vs);
|
|
||||||
glDeleteShader(fs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
shader_ = glCreateProgram();
|
|
||||||
glAttachShader(shader_, vs);
|
|
||||||
glAttachShader(shader_, fs);
|
|
||||||
glLinkProgram(shader_);
|
|
||||||
|
|
||||||
glGetProgramiv(shader_, GL_LINK_STATUS, &success);
|
|
||||||
glDeleteShader(vs);
|
|
||||||
glDeleteShader(fs);
|
|
||||||
|
|
||||||
return success == GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteRenderer::flush() {
|
void SpriteRenderer::flush() {
|
||||||
if (vertexCount_ == 0) return;
|
if (vertexCount_ == 0 || !material_) return;
|
||||||
|
|
||||||
vbo_->update(0, vertexCount_ * sizeof(SpriteVertex), vertices_.data());
|
vbo_->update(0, vertexCount_ * sizeof(SpriteVertex), vertices_.data());
|
||||||
|
|
||||||
if (material_ && material_->shader()) {
|
ShaderAsset* shader = nullptr;
|
||||||
material_->shader()->bind();
|
|
||||||
material_->shader()->applyStates();
|
|
||||||
|
|
||||||
GLint vpLoc = material_->shader()->getUniformLocation("u_viewProjection");
|
|
||||||
if (vpLoc >= 0) {
|
|
||||||
glUniformMatrix4fv(vpLoc, 1, GL_FALSE, &viewProjection_[0][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint texLoc = material_->shader()->getUniformLocation("u_texture");
|
|
||||||
if (texLoc >= 0) {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, currentTexture_);
|
|
||||||
glUniform1i(texLoc, 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
glUseProgram(shader_);
|
|
||||||
GLint vpLoc = glGetUniformLocation(shader_, "u_viewProjection");
|
|
||||||
glUniformMatrix4fv(vpLoc, 1, GL_FALSE, &viewProjection_[0][0]);
|
|
||||||
|
|
||||||
GLint texLoc = glGetUniformLocation(shader_, "u_texture");
|
|
||||||
glUniform1i(texLoc, 0);
|
|
||||||
|
|
||||||
glBindTextureUnit(0, currentTexture_);
|
|
||||||
}
|
|
||||||
|
|
||||||
vao_->bind();
|
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount_ / VERTICES_PER_SPRITE * INDICES_PER_SPRITE),
|
|
||||||
GL_UNSIGNED_SHORT, nullptr);
|
|
||||||
|
|
||||||
E2D_RENDER_STATS().addDrawCall(static_cast<uint32>(vertexCount_),
|
|
||||||
static_cast<uint32>(vertexCount_ / 3));
|
|
||||||
|
|
||||||
drawCalls_++;
|
|
||||||
vertexCount_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteRenderer::flushWithMaterial() {
|
|
||||||
if (vertexCount_ == 0) return;
|
|
||||||
|
|
||||||
vbo_->update(0, vertexCount_ * sizeof(SpriteVertex), vertices_.data());
|
|
||||||
|
|
||||||
if (currentInstance_) {
|
if (currentInstance_) {
|
||||||
currentInstance_->apply();
|
currentInstance_->apply();
|
||||||
|
shader = currentInstance_->shader();
|
||||||
|
} else {
|
||||||
|
material_->apply();
|
||||||
|
shader = material_->shader();
|
||||||
|
}
|
||||||
|
|
||||||
ShaderAsset* shader = currentInstance_->shader();
|
|
||||||
if (shader) {
|
if (shader) {
|
||||||
GLint vpLoc = shader->getUniformLocation("u_viewProjection");
|
GLint vpLoc = shader->getUniformLocation("u_viewProjection");
|
||||||
if (vpLoc >= 0) {
|
if (vpLoc >= 0) {
|
||||||
|
|
@ -252,7 +129,6 @@ void SpriteRenderer::flushWithMaterial() {
|
||||||
glUniform1i(texLoc, 0);
|
glUniform1i(texLoc, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
vao_->bind();
|
vao_->bind();
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount_ / VERTICES_PER_SPRITE * INDICES_PER_SPRITE),
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount_ / VERTICES_PER_SPRITE * INDICES_PER_SPRITE),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue