refactor: Refactor shader uniform management

This commit is contained in:
Vsevolod Kremianskii 2020-09-30 12:28:37 +07:00
parent ef2d119783
commit a541782f08
15 changed files with 531 additions and 412 deletions

View file

@ -123,24 +123,26 @@ void Console::executeInputText() {
void Console::render() const {
float height = kLineCount * _font->height();
{
glm::mat4 transform(1.0f);
transform = glm::scale(transform, glm::vec3(_opts.width, height, 1.0f));
glm::mat4 model(1.0f);
model = glm::scale(model, glm::vec3(_opts.width, height, 1.0f));
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("model", model);
shaders.setUniform("color", glm::vec3(0.0f));
shaders.setUniform("alpha", 0.5f);
LocalUniforms locals;
locals.model = move(transform);
locals.color = glm::vec3(0.0f);
locals.alpha = 0.5f;
Shaders.activate(ShaderProgram::GUIGUI, locals);
}
DefaultQuad.render(GL_TRIANGLES);
string text("> " + _inputText);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(3.0f, height - 0.5f * _font->height(), 0.0f));
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(3.0f, height - 0.5f * _font->height(), 0.0f));
_font->render(text, transform, glm::vec3(1.0f), TextGravity::Right);
_font->render(text, transform, glm::vec3(1.0f), TextGravity::Right);
}
}
bool Console::isOpen() const {

View file

@ -223,10 +223,10 @@ void Game::drawWorld() {
void Game::drawGUI() {
glDisable(GL_DEPTH_TEST);
ShaderUniforms uniforms;
uniforms.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
GlobalUniforms globals;
globals.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
Shaders.setGlobalUniforms(uniforms);
Shaders.setGlobalUniforms(globals);
switch (_screen) {
case Screen::InGame:
@ -252,10 +252,10 @@ void Game::drawGUI() {
void Game::drawGUI3D() {
glDisable(GL_DEPTH_TEST);
ShaderUniforms uniforms;
uniforms.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
GlobalUniforms globals;
globals.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
Shaders.setGlobalUniforms(uniforms);
Shaders.setGlobalUniforms(globals);
switch (_screen) {
case Screen::MainMenu:
@ -271,10 +271,11 @@ void Game::drawGUI3D() {
void Game::drawCursor() {
glDisable(GL_DEPTH_TEST);
ShaderUniforms uniforms;
uniforms.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
GlobalUniforms globals;
globals.projection = glm::ortho(0.0f, static_cast<float>(_options.graphics.width), static_cast<float>(_options.graphics.height), 0.0f);
globals.view = glm::mat4(1.0f);
Shaders.setGlobalUniforms(uniforms);
Shaders.setGlobalUniforms(globals);
_window.drawCursor();
}

View file

@ -23,6 +23,8 @@
#include "../../render/shaders.h"
#include "../../resources/resources.h"
using namespace std;
using namespace reone::render;
using namespace reone::resources;
@ -55,10 +57,10 @@ void TargetOverlay::drawReticle(Texture &texture, const glm::vec3 &screenCoords)
transform = glm::translate(transform, glm::vec3((_opts.width * screenCoords.x) - width / 2, (_opts.height * (1.0f - screenCoords.y)) - height / 2, 0.0f));
transform = glm::scale(transform, glm::vec3(width, height, 1.0f));
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("model", transform);
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = move(transform);
Shaders.activate(ShaderProgram::GUIGUI, locals);
glActiveTexture(GL_TEXTURE0);
texture.bind();

View file

@ -212,11 +212,6 @@ void Control::update(float dt) {
void Control::render(const glm::ivec2 &offset, const string &textOverride) const {
if (!_visible) return;
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("color", glm::vec3(1.0f));
shaders.setUniform("alpha", 1.0f);
glm::ivec2 size(_extent.width, _extent.height);
if (_focus && _hilight) {
@ -233,6 +228,7 @@ void Control::render(const glm::ivec2 &offset, const string &textOverride) const
void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const glm::ivec2 &size) const {
ShaderManager &shaders = Shaders;
Quad &defaultQuad = DefaultQuad;
Quad &xFlippedQuad = XFlippedQuad;
Quad &yFlippedQuad = YFlippedQuad;
@ -241,15 +237,22 @@ void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const g
glActiveTexture(GL_TEXTURE0);
if (border.fill) {
int x = _extent.left + border.dimension + offset.x;
int y = _extent.top + border.dimension + offset.y;
int w = size.x - 2 * border.dimension;
int h = size.y - 2 * border.dimension;
{
int x = _extent.left + border.dimension + offset.x;
int y = _extent.top + border.dimension + offset.y;
int w = size.x - 2 * border.dimension;
int h = size.y - 2 * border.dimension;
glm::mat4 transform(glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f)));
transform = glm::scale(transform, glm::vec3(w, h, 1.0f));
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(w, h, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
shaders.activate(ShaderProgram::GUIGUI, locals);
}
shaders.setUniform("model", transform);
border.fill->bind();
GLint blendSrcRgb, blendSrcAlpha, blendDstRgb, blendDstAlpha;
@ -261,20 +264,17 @@ void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const g
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstAlpha);
glBlendFunc(GL_ONE, GL_ONE);
}
defaultQuad.render(GL_TRIANGLES);
if (additive) {
glBlendFuncSeparate(blendSrcRgb, blendDstRgb, blendSrcAlpha, blendDstAlpha);
}
border.fill->unbind();
}
if (border.edge) {
int width = size.x - 2 * border.dimension;
int height = size.y - 2 * border.dimension;
glm::mat4 edgeTransform(1.0f);
shaders.setUniform("color", border.color);
border.edge->bind();
if (height > 0.0f) {
@ -282,18 +282,34 @@ void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const g
int y = _extent.top + border.dimension + offset.y;
// Left edge
edgeTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
edgeTransform = glm::scale(edgeTransform, glm::vec3(border.dimension, height, 1.0f));
edgeTransform = glm::rotate(edgeTransform, glm::half_pi<float>(), glm::vec3(0.0f, 0.0f, 1.0f));
edgeTransform = glm::rotate(edgeTransform, glm::pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
shaders.setUniform("model", edgeTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, height, 1.0f));
transform = glm::rotate(transform, glm::half_pi<float>(), glm::vec3(0.0f, 0.0f, 1.0f));
transform = glm::rotate(transform, glm::pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
defaultQuad.render(GL_TRIANGLES);
// Right edge
edgeTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x + size.x, y, 0.0f));
edgeTransform = glm::scale(edgeTransform, glm::vec3(border.dimension, height, 1.0f));
edgeTransform = glm::rotate(edgeTransform, glm::half_pi<float>(), glm::vec3(0.0f, 0.0f, 1.0f));
shaders.setUniform("model", edgeTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x + size.x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, height, 1.0f));
transform = glm::rotate(transform, glm::half_pi<float>(), glm::vec3(0.0f, 0.0f, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
xFlippedQuad.render(GL_TRIANGLES);
}
@ -302,15 +318,31 @@ void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const g
int y = _extent.top + offset.y;
// Top edge
edgeTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
edgeTransform = glm::scale(edgeTransform, glm::vec3(width, border.dimension, 1.0f));
shaders.setUniform("model", edgeTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(width, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
defaultQuad.render(GL_TRIANGLES);
// Bottom edge
edgeTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x, y + size.y - border.dimension, 0.0f));
edgeTransform = glm::scale(edgeTransform, glm::vec3(width, border.dimension, 1.0f));
shaders.setUniform("model", edgeTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y + size.y - border.dimension, 0.0f));
transform = glm::scale(transform, glm::vec3(width, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
yFlippedQuad.render(GL_TRIANGLES);
}
@ -319,31 +351,63 @@ void Control::drawBorder(const Border &border, const glm::ivec2 &offset, const g
if (border.corner) {
int x = _extent.left + offset.x;
int y = _extent.top + offset.y;
glm::mat4 cornerTransform(1.0f);
border.corner->bind();
// Top left corner
cornerTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f));
cornerTransform = glm::scale(cornerTransform, glm::vec3(border.dimension, border.dimension, 1.0f));
shaders.setUniform("model", cornerTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
defaultQuad.render(GL_TRIANGLES);
// Bottom left corner
cornerTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x, y + size.y - border.dimension, 0.0f));
cornerTransform = glm::scale(cornerTransform, glm::vec3(border.dimension, border.dimension, 1.0f));
shaders.setUniform("model", cornerTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y + size.y - border.dimension, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
yFlippedQuad.render(GL_TRIANGLES);
// Top right corner
cornerTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x + size.x - border.dimension, y, 0.0f));
cornerTransform = glm::scale(cornerTransform, glm::vec3(border.dimension, border.dimension, 1.0f));
shaders.setUniform("model", cornerTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x + size.x - border.dimension, y, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
xFlippedQuad.render(GL_TRIANGLES);
// Bottom right corner
cornerTransform = glm::translate(glm::mat4(1.0f), glm::vec3(x + size.x - border.dimension, y + size.y - border.dimension, 0.0f));
cornerTransform = glm::scale(cornerTransform, glm::vec3(border.dimension, border.dimension, 1.0f));
shaders.setUniform("model", cornerTransform);
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x + size.x - border.dimension, y + size.y - border.dimension, 0.0f));
transform = glm::scale(transform, glm::vec3(border.dimension, border.dimension, 1.0f));
LocalUniforms locals;
locals.model = move(transform);
locals.color = border.color;
shaders.activate(ShaderProgram::GUIGUI, locals);
}
xyFlippedQuad.render(GL_TRIANGLES);
border.corner->unbind();
@ -438,21 +502,21 @@ void Control::render3D(const glm::ivec2 &offset) const {
glGetIntegerv(GL_VIEWPORT, viewport);
ShaderManager &shaders = Shaders;
ShaderUniforms uniforms;
Framebuffer *framebuffer = _scene3d.framebuffer.get();
// Render to framebuffer
{
GlobalUniforms globals;
globals.projection = glm::ortho(
0.0f,
static_cast<float>(framebuffer->width()),
static_cast<float>(framebuffer->height()),
0.0f,
-1024.0f,
1024.0f);
uniforms.projection = glm::ortho(
0.0f,
static_cast<float>(framebuffer->width()),
static_cast<float>(framebuffer->height()),
0.0f,
-1024.0f,
1024.0f);
shaders.setGlobalUniforms(uniforms);
shaders.setGlobalUniforms(globals);
}
framebuffer->bind();
glEnable(GL_DEPTH_TEST);
@ -466,19 +530,21 @@ void Control::render3D(const glm::ivec2 &offset) const {
framebuffer->unbind();
// Render control
{
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + offset.y, 0.0f));
transform = glm::scale(transform, glm::vec3(_extent.width, _extent.height, 1.0f));
uniforms.projection = glm::ortho(0.0f, static_cast<float>(viewport[2]), static_cast<float>(viewport[3]), 0.0f);
shaders.setGlobalUniforms(uniforms);
GlobalUniforms globals;
globals.projection = glm::ortho(0.0f, static_cast<float>(viewport[2]), static_cast<float>(viewport[3]), 0.0f);
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + offset.y, 0.0f));
transform = glm::scale(transform, glm::vec3(_extent.width, _extent.height, 1.0f));
shaders.setGlobalUniforms(globals);
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("model", transform);
shaders.setUniform("color", glm::vec3(1.0f));
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = move(transform);
shaders.activate(ShaderProgram::GUIGUI, locals);
}
glActiveTexture(GL_TEXTURE0);
framebuffer->bindTexture();

View file

@ -35,11 +35,6 @@ ImageButton::ImageButton() : Control(ControlType::ImageButton) {
void ImageButton::render(const glm::ivec2 &offset, const string &textOverride, const shared_ptr<Texture> &icon) const {
if (!_visible) return;
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("color", glm::vec3(1.0f));
shaders.setUniform("alpha", 1.0f);
glm::ivec2 borderOffset(offset);
borderOffset.x += _extent.height;
@ -62,22 +57,25 @@ void ImageButton::render(const glm::ivec2 &offset, const string &textOverride, c
void ImageButton::drawIcon(const glm::ivec2 &offset, const shared_ptr<Texture> &icon) const {
if (!_iconFrame && !icon) return;
ShaderManager &shaders = Shaders;
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(offset.x + _extent.left, offset.y + _extent.top, 0.0f));
transform = glm::scale(transform, glm::vec3(_extent.height, _extent.height, 1.0f));
{
glm::vec3 frameColor(1.0f);
if (_focus && _hilight) {
frameColor = _hilight->color;
} else if (_border) {
frameColor = _border->color;
}
glm::vec3 frameColor(1.0f);
if (_focus && _hilight) {
frameColor = _hilight->color;
} else if (_border) {
frameColor = _border->color;
LocalUniforms locals;
locals.model = transform;
locals.color = move(frameColor);
shaders.activate(ShaderProgram::GUIGUI, locals);
}
ShaderManager &shaders = Shaders;
shaders.setUniform("model", transform);
shaders.setUniform("color", frameColor);
shaders.setUniform("alpha", 1.0f);
glActiveTexture(0);
if (_iconFrame) {
@ -85,9 +83,12 @@ void ImageButton::drawIcon(const glm::ivec2 &offset, const shared_ptr<Texture> &
DefaultQuad.render(GL_TRIANGLES);
_iconFrame->unbind();
}
{
LocalUniforms locals;
locals.model = transform;
shaders.setUniform("color", glm::vec3(1.0f));
shaders.activate(ShaderProgram::GUIGUI, locals);
}
if (icon) {
icon->bind();
DefaultQuad.render(GL_TRIANGLES);

View file

@ -50,10 +50,6 @@ void ScrollBar::load(const GffStruct &gffs) {
void ScrollBar::render(const glm::ivec2 &offset, const string &textOverride) const {
if (!_dir.image) return;
Shaders.activate(ShaderProgram::GUIGUI);
Shaders.setUniform("color", glm::vec3(1.0f));
Shaders.setUniform("alpha", 1.0f);
glActiveTexture(0);
_dir.image->bind();
@ -64,21 +60,27 @@ void ScrollBar::render(const glm::ivec2 &offset, const string &textOverride) con
}
void ScrollBar::drawUpArrow(const glm::vec2 &offset) const {
glm::mat4 arrowTransform(glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + offset.x, _extent.top + offset.y, 0.0f)));
arrowTransform = glm::scale(arrowTransform, glm::vec3(_extent.width, _extent.width, 1.0f));
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + offset.y, 0.0f));
transform = glm::scale(transform, glm::vec3(_extent.width, _extent.width, 1.0f));
Shaders.setUniform("model", arrowTransform);
LocalUniforms locals;
locals.model = move(transform);
Shaders.activate(ShaderProgram::GUIGUI, locals);
DefaultQuad.render(GL_TRIANGLES);
}
void ScrollBar::drawDownArrow(const glm::vec2 &offset) const {
glm::mat4 arrowTransform(glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + offset.x, _extent.top + _extent.height + offset.y, 0.0f)));
arrowTransform = glm::scale(arrowTransform, glm::vec3(_extent.width, _extent.width, 1.0f));
arrowTransform = glm::rotate(arrowTransform, glm::pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + _extent.height + offset.y, 0.0f));
transform = glm::scale(transform, glm::vec3(_extent.width, _extent.width, 1.0f));
transform = glm::rotate(transform, glm::pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
Shaders.setUniform("model", arrowTransform);
LocalUniforms locals;
locals.model = move(transform);
Shaders.activate(ShaderProgram::GUIGUI, locals);
DefaultQuad.render(GL_TRIANGLES);
}

View file

@ -231,13 +231,13 @@ void GUI::render() const {
}
void GUI::drawBackground() const {
glm::mat4 transform(glm::scale(glm::mat4(1.0f), glm::vec3(_gfxOpts.width, _gfxOpts.height, 1.0f)));
glm::mat4 transform(1.0f);
transform = glm::scale(transform, glm::vec3(_gfxOpts.width, _gfxOpts.height, 1.0f));
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("model", transform);
shaders.setUniform("color", glm::vec3(1.0f));
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = move(transform);
Shaders.activate(ShaderProgram::GUIGUI, locals);
glActiveTexture(0);
_background->bind();

View file

@ -111,8 +111,6 @@ void Font::render(const string &text, const glm::mat4 &transform, const glm::vec
if (text.empty()) return;
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("color", color);
assert(_texture);
glActiveTexture(GL_TEXTURE0);
@ -139,8 +137,11 @@ void Font::render(const string &text, const glm::mat4 &transform, const glm::vec
glm::mat4 textTransform(glm::translate(transform, textOffset));
for (auto &glyph : text) {
assert(glyph < _glyphCount);
shaders.setUniform("model", textTransform);
LocalUniforms locals;
locals.model = textTransform;
locals.color = color;
shaders.activate(ShaderProgram::GUIGUI, locals);
int off = kIndicesPerGlyph * glyph * sizeof(uint16_t);
glDrawElements(GL_TRIANGLES, kIndicesPerGlyph, GL_UNSIGNED_SHORT, reinterpret_cast<void *>(off));

View file

@ -63,12 +63,12 @@ AABBMesh::AABBMesh() {
}
void AABBMesh::render(const AABB &aabb, const glm::mat4 &transform) const {
glm::mat4 transform2(transform * aabb.transform());
glm::mat4 finalTransform(transform * aabb.transform());
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::ModelWhite);
shaders.setUniform("model", transform2);
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = finalTransform;
Shaders.activate(ShaderProgram::ModelWhite, locals);
Mesh::render(GL_LINES);
}

View file

@ -61,10 +61,10 @@ CubeMesh::CubeMesh() {
}
void CubeMesh::render(const glm::mat4 &transform) const {
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::ModelWhite);
shaders.setUniform("model", transform);
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = transform;
Shaders.activate(ShaderProgram::ModelWhite, locals);
Mesh::render(GL_TRIANGLES);
}

View file

@ -55,53 +55,36 @@ void MeshSceneNode::updateDistanceToCamera(const glm::vec3 &cameraPosition) {
_distanceToCamera = glm::distance2(_center, cameraPosition);
}
static const string &getLightUniformName(int index, const char *propName) {
static unordered_map<int, unordered_map<const char *, string>> cache;
auto &cacheByIndex = cache[index];
auto nameIt = cacheByIndex.find(propName);
if (nameIt != cacheByIndex.end()) {
return nameIt->second;
}
string name(str(boost::format("lights[%d].%s") % index % propName));
auto pair = cacheByIndex.insert(make_pair(propName, name));
return pair.first->second;
}
void MeshSceneNode::render() const {
shared_ptr<ModelMesh> mesh(_modelNode->mesh());
shared_ptr<ModelNode::Skin> skin(_modelNode->skin());
const ModelSceneNode::AnimationState &animState = _model->animationState();
bool skeletal = skin && !animState.name.empty();
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::ModelModel);
shaders.setUniform("model", _absoluteTransform);
shaders.setUniform("alpha", _model->alpha() * _modelNode->alpha());
LocalUniforms locals;
locals.model = _absoluteTransform;
locals.alpha = _model->alpha() * _modelNode->alpha();
if (mesh->hasEnvmapTexture()) {
shaders.setUniform("envmapEnabled", true);
shaders.setUniform("envmap", 1);
locals.features.envmapEnabled = true;
locals.textures.envmap = 1;
}
if (mesh->hasLightmapTexture()) {
shaders.setUniform("lightmapEnabled", true);
shaders.setUniform("lightmap", 2);
locals.features.lightmapEnabled = true;
locals.textures.lightmap = 2;
}
if (mesh->hasBumpyShinyTexture()) {
shaders.setUniform("bumpyShinyEnabled", true);
shaders.setUniform("bumpyShiny", 3);
locals.features.bumpyShinyEnabled = true;
locals.textures.bumpyShiny = 3;
}
if (mesh->hasBumpmapTexture()) {
shaders.setUniform("bumpmapEnabled", true);
shaders.setUniform("bumpmap", 4);
locals.features.bumpmapEnabled = true;
locals.textures.bumpmap = 4;
}
if (skeletal) {
shaders.setUniform("skeletalEnabled", true);
shaders.setUniform("absTransform", _modelNode->absoluteTransform());
shaders.setUniform("absTransformInv", _modelNode->absoluteTransformInverse());
locals.features.skeletalEnabled = true;
locals.skeletal.absTransform = _modelNode->absoluteTransform();
locals.skeletal.absTransformInv = _modelNode->absoluteTransformInverse();
const unordered_map<uint16_t, uint16_t> &nodeIdxByBoneIdx = skin->nodeIdxByBoneIdx;
vector<glm::mat4> bones(nodeIdxByBoneIdx.size(), glm::mat4(1.0f));
@ -116,58 +99,34 @@ void MeshSceneNode::render() const {
bones[boneIdx] = bone->second;
}
shaders.setUniform("bones", bones);
locals.skeletal.bones = move(bones);
}
if (_modelNode->isSelfIllumEnabled()) {
shaders.setUniform("selfIllumEnabled", true);
shaders.setUniform("selfIllumColor", _modelNode->selfIllumColor());
locals.features.selfIllumEnabled = true;
locals.selfIllumColor = _modelNode->selfIllumColor();
}
int lightCount = 0;
if (_model->isLightingEnabled()) {
const vector<LightSceneNode *> &lights = _model->lightsAffectedBy();
lightCount = static_cast<int>(lights.size());
shaders.setUniform("lightingEnabled", true);
shaders.setUniform("lightCount", lightCount);
shaders.setUniform("ambientLightColor", _sceneGraph->ambientLightColor());
locals.features.lightingEnabled = true;
locals.lighting.ambientColor = _sceneGraph->ambientLightColor();
locals.lighting.lights.clear();
for (int i = 0; i < lightCount; ++i) {
LightSceneNode *light = lights[i];
shaders.setUniform(getLightUniformName(i, "ambientOnly"), light->modelNode().light()->ambientOnly);
shaders.setUniform(getLightUniformName(i, "position"), glm::vec3(light->absoluteTransform()[3]));
shaders.setUniform(getLightUniformName(i, "radius"), light->modelNode().radius());
shaders.setUniform(getLightUniformName(i, "color"), light->modelNode().color());
shaders.setUniform(getLightUniformName(i, "multiplier"), light->modelNode().multiplier());
for (auto &light : lights) {
ShaderLight shaderLight;
shaderLight.position = light->absoluteTransform()[3];
shaderLight.radius = light->modelNode().radius();
shaderLight.color = light->modelNode().color();
locals.lighting.lights.push_back(move(shaderLight));
}
}
Shaders.activate(ShaderProgram::ModelModel, locals);
mesh->render(_model->textureOverride());
if (skeletal) {
shaders.setUniform("skeletalEnabled", false);
}
if (_model->isLightingEnabled()) {
shaders.setUniform("lightingEnabled", false);
}
if (_modelNode->isSelfIllumEnabled()) {
shaders.setUniform("selfIllumEnabled", false);
}
if (mesh->hasEnvmapTexture()) {
shaders.setUniform("envmapEnabled", false);
}
if (mesh->hasLightmapTexture()) {
shaders.setUniform("lightmapEnabled", false);
}
if (mesh->hasBumpyShinyTexture()) {
shaders.setUniform("bumpyShinyEnabled", false);
}
if (mesh->hasBumpmapTexture()) {
shaders.setUniform("bumpmapEnabled", false);
}
SceneNode::render();
}

View file

@ -86,12 +86,12 @@ void SceneGraph::render() const {
glEnable(GL_DEPTH_TEST);
ShaderUniforms uniforms;
uniforms.projection = _activeCamera->projection();
uniforms.view = _activeCamera->view();
uniforms.cameraPosition = _activeCamera->absoluteTransform()[3];
GlobalUniforms globals;
globals.projection = _activeCamera->projection();
globals.view = _activeCamera->view();
globals.cameraPosition = _activeCamera->absoluteTransform()[3];
Shaders.setGlobalUniforms(uniforms);
Shaders.setGlobalUniforms(globals);
for (auto &node : _rootNodes) {
node->render();

View file

@ -36,18 +36,18 @@ namespace render {
static const GLchar kGUIVertexShader[] = R"END(
#version 330
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 uProjection;
uniform mat4 uView;
uniform mat4 uModel;
layout(location = 0) in vec3 position;
layout(location = 2) in vec2 texCoords;
layout(location = 0) in vec3 aPosition;
layout(location = 2) in vec2 aTexCoords;
out vec2 fragTexCoords;
void main() {
gl_Position = projection * view * model * vec4(position, 1.0);
fragTexCoords = texCoords;
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
fragTexCoords = aTexCoords;
}
)END";
@ -56,21 +56,21 @@ static const GLchar kModelVertexShader[] = R"END(
const int MAX_BONES = 128;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 uProjection;
uniform mat4 uView;
uniform mat4 uModel;
uniform bool skeletalEnabled;
uniform mat4 absTransform;
uniform mat4 absTransformInv;
uniform mat4 bones[MAX_BONES];
uniform bool uSkeletalEnabled;
uniform mat4 uAbsTransform;
uniform mat4 uAbsTransformInv;
uniform mat4 uBones[MAX_BONES];
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoords;
layout(location = 3) in vec2 lightmapCoords;
layout(location = 4) in vec4 boneWeights;
layout(location = 5) in vec4 boneIndices;
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoords;
layout(location = 3) in vec2 aLightmapCoords;
layout(location = 4) in vec4 aBoneWeights;
layout(location = 5) in vec4 aBoneIndices;
out vec3 fragPosition;
out vec3 fragNormal;
@ -80,64 +80,63 @@ out vec2 fragLightmapCoords;
void main() {
vec3 newPosition = vec3(0.0);
if (skeletalEnabled) {
float weight0 = boneWeights.x;
float weight1 = boneWeights.y;
float weight2 = boneWeights.z;
float weight3 = boneWeights.w;
if (uSkeletalEnabled) {
float weight0 = aBoneWeights.x;
float weight1 = aBoneWeights.y;
float weight2 = aBoneWeights.z;
float weight3 = aBoneWeights.w;
int index0 = int(boneIndices.x);
int index1 = int(boneIndices.y);
int index2 = int(boneIndices.z);
int index3 = int(boneIndices.w);
int index0 = int(aBoneIndices.x);
int index1 = int(aBoneIndices.y);
int index2 = int(aBoneIndices.z);
int index3 = int(aBoneIndices.w);
vec4 position4 = vec4(position, 1.0);
vec4 position4 = vec4(aPosition, 1.0);
newPosition += weight0 * (absTransformInv * bones[index0] * absTransform * position4).xyz;
newPosition += weight1 * (absTransformInv * bones[index1] * absTransform * position4).xyz;
newPosition += weight2 * (absTransformInv * bones[index2] * absTransform * position4).xyz;
newPosition += weight3 * (absTransformInv * bones[index3] * absTransform * position4).xyz;
newPosition += weight0 * (uAbsTransformInv * uBones[index0] * uAbsTransform * position4).xyz;
newPosition += weight1 * (uAbsTransformInv * uBones[index1] * uAbsTransform * position4).xyz;
newPosition += weight2 * (uAbsTransformInv * uBones[index2] * uAbsTransform * position4).xyz;
newPosition += weight3 * (uAbsTransformInv * uBones[index3] * uAbsTransform * position4).xyz;
} else {
newPosition = position;
newPosition = aPosition;
}
vec4 newPosition4 = vec4(newPosition, 1.0);
gl_Position = projection * view * model * newPosition4;
fragPosition = vec3(model * newPosition4);
fragNormal = mat3(transpose(inverse(model))) * normal;
fragTexCoords = texCoords;
fragLightmapCoords = lightmapCoords;
gl_Position = uProjection * uView * uModel * newPosition4;
fragPosition = vec3(uModel * newPosition4);
fragNormal = mat3(transpose(inverse(uModel))) * aNormal;
fragTexCoords = aTexCoords;
fragLightmapCoords = aLightmapCoords;
}
)END";
static const GLchar kWhiteFragmentShader[] = R"END(
#version 330
uniform float alpha;
uniform float uAlpha;
out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 1.0, 1.0, alpha);
fragColor = vec4(1.0, 1.0, 1.0, uAlpha);
}
)END";
static const GLchar kGUIFragmentShader[] = R"END(
#version 330
uniform sampler2D image;
uniform vec3 color;
uniform float alpha;
uniform sampler2D uTexture;
uniform vec3 uColor;
uniform float uAlpha;
in vec2 fragTexCoords;
out vec4 fragColor;
void main() {
vec4 imageSample = texture(image, fragTexCoords);
fragColor = vec4(color * imageSample.rgb, alpha * imageSample.a);
vec4 textureSample = texture(uTexture, fragTexCoords);
fragColor = vec4(uColor * textureSample.rgb, uAlpha * textureSample.a);
}
)END";
@ -147,32 +146,33 @@ static const GLchar kModelFragmentShader[] = R"END(
const int MAX_LIGHTS = 8;
const vec3 RGB_TO_LUMINOSITY = vec3(0.2126, 0.7152, 0.0722);
uniform struct Light {
struct Light {
vec3 position;
float radius;
vec3 color;
float multiplier;
} lights[MAX_LIGHTS];
float radius;
};
uniform bool lightmapEnabled;
uniform bool envmapEnabled;
uniform bool bumpyShinyEnabled;
uniform bool bumpmapEnabled;
uniform bool lightingEnabled;
uniform bool selfIllumEnabled;
uniform bool uLightmapEnabled;
uniform bool uEnvmapEnabled;
uniform bool uBumpyShinyEnabled;
uniform bool uBumpmapEnabled;
uniform bool uSkeletalEnabled;
uniform bool uLightingEnabled;
uniform bool uSelfIllumEnabled;
uniform sampler2D diffuse;
uniform sampler2D lightmap;
uniform sampler2D bumpmap;
uniform samplerCube envmap;
uniform samplerCube bumpyShiny;
uniform sampler2D uDiffuse;
uniform sampler2D uLightmap;
uniform sampler2D uBumpmap;
uniform samplerCube uEnvmap;
uniform samplerCube uBumpyShiny;
uniform vec3 cameraPosition;
uniform float alpha;
uniform vec3 uCameraPosition;
uniform float uAlpha;
uniform int lightCount;
uniform vec3 ambientLightColor;
uniform vec3 selfIllumColor;
uniform int uLightCount;
uniform vec3 uAmbientLightColor;
uniform vec3 uSelfIllumColor;
uniform Light uLights[MAX_LIGHTS];
in vec3 fragPosition;
in vec3 fragNormal;
@ -182,12 +182,12 @@ in vec2 fragLightmapCoords;
out vec4 fragColor;
void applyLightmap(inout vec3 color) {
vec4 lightmapSample = texture(lightmap, fragLightmapCoords);
vec4 lightmapSample = texture(uLightmap, fragLightmapCoords);
color *= lightmapSample.rgb;
}
void applyEnvmap(samplerCube image, vec3 normal, float a, inout vec3 color) {
vec3 I = normalize(fragPosition - cameraPosition);
vec3 I = normalize(fragPosition - uCameraPosition);
vec3 R = reflect(I, normal);
vec4 sample = texture(image, R);
@ -195,15 +195,15 @@ void applyEnvmap(samplerCube image, vec3 normal, float a, inout vec3 color) {
}
void applyLighting(vec3 normal, inout vec3 color) {
color += ambientLightColor;
color += uAmbientLightColor;
if (lightCount == 0) return;
if (uLightCount == 0) return;
for (int i = 0; i < lightCount; ++i) {
vec3 surfaceToLight = lights[i].position - fragPosition;
for (int i = 0; i < uLightCount; ++i) {
vec3 surfaceToLight = uLights[i].position - fragPosition;
vec3 lightDir = normalize(surfaceToLight);
vec3 surfaceToCamera = normalize(cameraPosition - fragPosition);
vec3 surfaceToCamera = normalize(uCameraPosition - fragPosition);
float diffuseCoeff = max(dot(normal, lightDir), 0.0);
float specularCoeff = 0.0;
@ -212,46 +212,46 @@ void applyLighting(vec3 normal, inout vec3 color) {
}
float distToLight = length(surfaceToLight);
float attenuation = clamp(1.0 - distToLight / lights[i].radius, 0.0, 1.0);
float attenuation = clamp(1.0 - distToLight / uLights[i].radius, 0.0, 1.0);
attenuation *= attenuation;
color += attenuation * (diffuseCoeff + specularCoeff) * lights[i].color;
color += attenuation * (diffuseCoeff + specularCoeff) * uLights[i].color;
}
}
void applySelfIllum(inout vec3 color) {
vec4 diffuseSample = texture(diffuse, fragTexCoords);
vec4 diffuseSample = texture(uDiffuse, fragTexCoords);
float luminosity = dot(diffuseSample.rgb, RGB_TO_LUMINOSITY);
color += 0.5 * smoothstep(0.5, 1.0, luminosity) * selfIllumColor;
color += 0.5 * smoothstep(0.5, 1.0, luminosity) * uSelfIllumColor;
}
void main() {
vec4 diffuseSample = texture(diffuse, fragTexCoords);
vec4 diffuseSample = texture(uDiffuse, fragTexCoords);
vec3 surfaceColor = diffuseSample.rgb;
vec3 lightColor = vec3(0.0);
vec3 normal = normalize(fragNormal);
if (lightmapEnabled) {
if (uLightmapEnabled) {
applyLightmap(surfaceColor);
}
if (envmapEnabled) {
applyEnvmap(envmap, normal, 1.0 - diffuseSample.a, surfaceColor);
} else if (bumpyShinyEnabled) {
applyEnvmap(bumpyShiny, normal, 1.0 - diffuseSample.a, surfaceColor);
if (uEnvmapEnabled) {
applyEnvmap(uEnvmap, normal, 1.0 - diffuseSample.a, surfaceColor);
} else if (uBumpyShinyEnabled) {
applyEnvmap(uBumpyShiny, normal, 1.0 - diffuseSample.a, surfaceColor);
}
if (lightingEnabled) {
if (uLightingEnabled) {
applyLighting(normal, lightColor);
lightColor = min(lightColor, 1.0);
} else {
lightColor = vec3(1.0);
}
if (selfIllumEnabled) {
if (uSelfIllumEnabled) {
applySelfIllum(lightColor);
}
float finalAlpha = alpha;
float finalAlpha = uAlpha;
if (!envmapEnabled && !bumpyShinyEnabled) {
if (!uEnvmapEnabled && !uBumpyShinyEnabled) {
finalAlpha *= diffuseSample.a;
}
fragColor = vec4(lightColor * surfaceColor, finalAlpha);
@ -261,20 +261,20 @@ void main() {
static const GLchar kGaussianBlurFragmentShader[] = R"END(
#version 330
uniform sampler2D image;
uniform vec2 resolution;
uniform vec2 direction;
uniform sampler2D uTexture;
uniform vec2 uResolution;
uniform vec2 uDirection;
out vec4 fragColor;
void main() {
vec2 uv = vec2(gl_FragCoord.xy / resolution);
vec2 off1 = vec2(1.3333333333333333) * direction;
vec2 uv = vec2(gl_FragCoord.xy / uResolution);
vec2 off1 = vec2(1.3333333333333333) * uDirection;
vec4 color = vec4(0.0);
color += texture2D(image, uv) * 0.29411764705882354;
color += texture2D(image, uv + (off1 / resolution)) * 0.35294117647058826;
color += texture2D(image, uv - (off1 / resolution)) * 0.35294117647058826;
color += texture2D(uTexture, uv) * 0.29411764705882354;
color += texture2D(uTexture, uv + (off1 / uResolution)) * 0.35294117647058826;
color += texture2D(uTexture, uv - (off1 / uResolution)) * 0.35294117647058826;
fragColor = color;
}
@ -354,13 +354,15 @@ void ShaderManager::deinitGL() {
_shaders.clear();
}
void ShaderManager::activate(ShaderProgram program) {
if (_activeProgram == program) return;
void ShaderManager::activate(ShaderProgram program, const LocalUniforms &locals) {
if (_activeProgram != program) {
unsigned int ordinal = getOrdinal(program);
glUseProgram(ordinal);
unsigned int ordinal = getOrdinal(program);
glUseProgram(ordinal);
_activeProgram = program;
_activeOrdinal = ordinal;
_activeProgram = program;
_activeOrdinal = ordinal;
}
setLocalUniforms(locals);
}
unsigned int ShaderManager::getOrdinal(ShaderProgram program) const {
@ -371,6 +373,109 @@ unsigned int ShaderManager::getOrdinal(ShaderProgram program) const {
return it->second;
}
static const string &getLightUniformName(int index, const char *propName) {
static unordered_map<int, unordered_map<const char *, string>> cache;
auto &cacheByIndex = cache[index];
auto maybeName = cacheByIndex.find(propName);
if (maybeName != cacheByIndex.end()) {
return maybeName->second;
}
string name(str(boost::format("uLights[%d].%s") % index % propName));
auto pair = cacheByIndex.insert(make_pair(propName, name));
return pair.first->second;
}
void ShaderManager::setLocalUniforms(const LocalUniforms &locals) {
setUniform("uModel", locals.model);
setUniform("uColor", locals.color);
setUniform("uAlpha", locals.alpha);
setUniform("uLightmapEnabled", locals.features.lightmapEnabled);
setUniform("uEnvmapEnabled", locals.features.envmapEnabled);
setUniform("uLightmapEnabled", locals.features.lightmapEnabled);
setUniform("uBumpyShinyEnabled", locals.features.bumpyShinyEnabled);
setUniform("uBumpmapEnabled", locals.features.bumpmapEnabled);
setUniform("uSkeletalEnabled", locals.features.skeletalEnabled);
setUniform("uLightingEnabled", locals.features.lightingEnabled);
setUniform("uSelfIllumEnabled", locals.features.selfIllumEnabled);
if (locals.features.lightmapEnabled) {
setUniform("uLightmap", locals.textures.lightmap);
}
if (locals.features.envmapEnabled) {
setUniform("uEnvmap", locals.textures.envmap);
}
if (locals.features.bumpyShinyEnabled) {
setUniform("uBumpyShiny", locals.textures.bumpyShiny);
}
if (locals.features.bumpmapEnabled) {
setUniform("uBumpmap", locals.textures.bumpmap);
}
if (locals.features.skeletalEnabled) {
setUniform("uAbsTransform", locals.skeletal.absTransform);
setUniform("uAbsTransformInv", locals.skeletal.absTransformInv);
setUniform("uBones", locals.skeletal.bones);
}
if (locals.features.lightingEnabled) {
int lightCount = static_cast<int>(locals.lighting.lights.size());
setUniform("uLightCount", lightCount);
setUniform("uAmbientLightColor", locals.lighting.ambientColor);
for (int i = 0; i < lightCount; ++i) {
const ShaderLight &light = locals.lighting.lights[i];
setUniform(getLightUniformName(i, "position"), light.position);
setUniform(getLightUniformName(i, "color"), light.color);
setUniform(getLightUniformName(i, "radius"), light.radius);
}
}
if (locals.features.selfIllumEnabled) {
setUniform("uSelfIllumColor", locals.selfIllumColor);
}
}
void ShaderManager::setUniform(const string &name, const glm::mat4 &m) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(m));
}
void ShaderManager::setUniform(const string &name, int value) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniform1i(loc, value);
}
void ShaderManager::setUniform(const string &name, float value) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniform1f(loc, value);
}
void ShaderManager::setUniform(const string &name, const glm::vec2 &v) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniform2f(loc, v.x, v.y);
}
void ShaderManager::setUniform(const string &name, const glm::vec3 &v) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniform3f(loc, v.x, v.y, v.z);
}
void ShaderManager::setUniform(const string &name, const vector<glm::mat4> &arr) {
GLint loc = glGetUniformLocation(_activeOrdinal, name.c_str());
if (loc == -1) return;
glUniformMatrix4fv(loc, static_cast<GLsizei>(arr.size()), GL_FALSE, reinterpret_cast<const GLfloat *>(&arr[0]));
}
void ShaderManager::deactivate() {
if (_activeProgram == ShaderProgram::None) return;
@ -379,82 +484,19 @@ void ShaderManager::deactivate() {
_activeOrdinal = 0;
}
void ShaderManager::setGlobalUniforms(const ShaderUniforms &uniforms) {
for (auto &pair : _programs) {
activate(pair.first);
void ShaderManager::setGlobalUniforms(const GlobalUniforms &globals) {
uint32_t ordinal = _activeOrdinal;
setUniform(_activeOrdinal, "projection", uniforms.projection);
setUniform(_activeOrdinal, "view", uniforms.view);
setUniform(_activeOrdinal, "cameraPosition", uniforms.cameraPosition);
for (auto &program : _programs) {
glUseProgram(program.second);
_activeOrdinal = program.second;
setUniform("uProjection", globals.projection);
setUniform("uView", globals.view);
setUniform("uCameraPosition", globals.cameraPosition);
}
deactivate();
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, const glm::mat4 &m) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(m));
}
void ShaderManager::setUniform(const string &name, int value) {
setUniform(_activeOrdinal, name, value);
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, int value) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniform1i(loc, value);
}
void ShaderManager::setUniform(const string &name, float value) {
setUniform(_activeOrdinal, name, value);
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, float value) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniform1f(loc, value);
}
void ShaderManager::setUniform(const string &name, const glm::vec2 &v) {
setUniform(_activeOrdinal, name, v);
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, const glm::vec2 &v) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniform2f(loc, v.x, v.y);
}
void ShaderManager::setUniform(const string &name, const glm::vec3 &v) {
setUniform(_activeOrdinal, name, v);
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, const glm::vec3 &v) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniform3f(loc, v.x, v.y, v.z);
}
void ShaderManager::setUniform(const string &name, const glm::mat4 &m) {
setUniform(_activeOrdinal, name, m);
}
void ShaderManager::setUniform(const string &name, const vector<glm::mat4> &arr) {
setUniform(_activeOrdinal, name, arr);
}
void ShaderManager::setUniform(unsigned int ordinal, const string &name, const vector<glm::mat4> &arr) {
GLint loc = glGetUniformLocation(ordinal, name.c_str());
if (loc == -1) return;
glUniformMatrix4fv(loc, static_cast<GLsizei>(arr.size()), GL_FALSE, reinterpret_cast<const GLfloat *>(&arr[0]));
glUseProgram(ordinal);
_activeOrdinal = ordinal;
}
} // namespace render

View file

@ -17,6 +17,7 @@
#pragma once
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
@ -34,27 +35,68 @@ enum class ShaderProgram {
ModelModel
};
struct ShaderUniforms {
struct GlobalUniforms {
glm::mat4 projection { 1.0f };
glm::mat4 view { 1.0f };
glm::vec3 cameraPosition { 0.0f };
};
struct FeatureUniforms {
bool lightmapEnabled { false };
bool envmapEnabled { false };
bool bumpyShinyEnabled { false };
bool bumpmapEnabled { false };
bool skeletalEnabled { false };
bool lightingEnabled { false };
bool selfIllumEnabled { false };
};
struct TextureUniforms {
int lightmap { 0 };
int envmap { 0 };
int bumpyShiny { 0 };
int bumpmap { 0 };
};
struct SkeletalUniforms {
glm::mat4 absTransform { 1.0f };
glm::mat4 absTransformInv { 1.0f };
std::vector<glm::mat4> bones;
};
struct ShaderLight {
glm::vec3 position { 0.0f };
glm::vec3 color { 1.0f };
float radius { 1.0f };
};
struct LightingUniforms {
glm::vec3 ambientColor { 1.0f };
std::vector<ShaderLight> lights;
};
struct LocalUniforms {
FeatureUniforms features;
TextureUniforms textures;
SkeletalUniforms skeletal;
LightingUniforms lighting;
glm::mat4 model { 1.0f };
glm::vec3 color { 1.0f };
float alpha { 1.0f };
glm::vec3 selfIllumColor { 1.0f };
};
class ShaderManager {
public:
static ShaderManager &instance();
void initGL();
void deinitGL();
void activate(ShaderProgram program);
void activate(ShaderProgram program, const LocalUniforms &uniforms);
void deactivate();
void setGlobalUniforms(const ShaderUniforms &uniforms);
void setUniform(const std::string &name, int value);
void setUniform(const std::string &name, float value);
void setUniform(const std::string &name, const glm::vec2 &v);
void setUniform(const std::string &name, const glm::vec3 &v);
void setUniform(const std::string &name, const glm::mat4 &m);
void setUniform(const std::string &name, const std::vector<glm::mat4> &arr);
void setGlobalUniforms(const GlobalUniforms &globals);
private:
enum class ShaderName {
@ -66,10 +108,10 @@ private:
FragmentGaussianBlur
};
std::unordered_map<ShaderName, unsigned int> _shaders;
std::unordered_map<ShaderProgram, unsigned int> _programs;
std::unordered_map<ShaderName, uint32_t> _shaders;
std::unordered_map<ShaderProgram, uint32_t> _programs;
ShaderProgram _activeProgram { ShaderProgram::None };
unsigned int _activeOrdinal { 0 };
uint32_t _activeOrdinal { 0 };
ShaderManager() = default;
ShaderManager(const ShaderManager &) = delete;
@ -80,12 +122,13 @@ private:
void initShader(ShaderName name, unsigned int type, const char *source);
void initProgram(ShaderProgram program, ShaderName vertexShader, ShaderName fragmentShader);
unsigned int getOrdinal(ShaderProgram program) const;
void setUniform(unsigned int ordinal, const std::string &name, int value);
void setUniform(unsigned int ordinal, const std::string &name, float value);
void setUniform(unsigned int ordinal, const std::string &name, const glm::vec2 &v);
void setUniform(unsigned int ordinal, const std::string &name, const glm::vec3 &v);
void setUniform(unsigned int ordinal, const std::string &name, const glm::mat4 &m);
void setUniform(unsigned int ordinal, const std::string &name, const std::vector<glm::mat4> &arr);
void setLocalUniforms(const LocalUniforms &locals);
void setUniform(const std::string &name, int value);
void setUniform(const std::string &name, float value);
void setUniform(const std::string &name, const glm::vec2 &v);
void setUniform(const std::string &name, const glm::vec3 &v);
void setUniform(const std::string &name, const glm::mat4 &m);
void setUniform(const std::string &name, const std::vector<glm::mat4> &arr);
};
#define Shaders render::ShaderManager::instance()

View file

@ -162,14 +162,14 @@ void RenderWindow::drawCursor() const {
if (!texture) return;
glm::mat4 transform(glm::translate(glm::mat4(1.0f), glm::vec3(x, y, 0.0f)));
glm::mat4 transform(1.0f);
transform = glm::translate(transform, glm::vec3(x, y, 0.0f));
transform = glm::scale(transform, glm::vec3(texture->width(), texture->height(), 1.0f));
ShaderManager &shaders = Shaders;
shaders.activate(ShaderProgram::GUIGUI);
shaders.setUniform("model", transform);
shaders.setUniform("color", glm::vec3(1.0f));
shaders.setUniform("alpha", 1.0f);
LocalUniforms locals;
locals.model = move(transform);
Shaders.activate(ShaderProgram::GUIGUI, locals);
glActiveTexture(0);
texture->bind();