From 4743bbad8051c4cf4f716035323c8b1a4cbb2f7f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 13 Jul 2015 16:18:39 -0700 Subject: [PATCH] Adding shaders to the lib for rendering simple textured quad and solve the ImageOverlay issue for edit.js --- interface/src/ui/ApplicationOverlay.cpp | 1 + interface/src/ui/overlays/ImageOverlay.cpp | 49 ++++++++++++++++++- interface/src/ui/overlays/Overlays.cpp | 5 +- libraries/gpu/src/gpu/DrawColoredTexture.slf | 22 +++++++++ .../gpu/DrawTexcoordRectTransformUnitQuad.slv | 39 +++++++++++++++ libraries/gpu/src/gpu/StandardShaderLib.cpp | 46 +++++++++++++++++ libraries/gpu/src/gpu/StandardShaderLib.h | 15 ++++++ .../src/DeferredLightingEffect.cpp | 6 +-- 8 files changed, 178 insertions(+), 5 deletions(-) create mode 100755 libraries/gpu/src/gpu/DrawColoredTexture.slf create mode 100755 libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 9f742093ee..44904a8655 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -127,6 +127,7 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glUseProgram(0); // give external parties a change to hook in emit qApp->renderingOverlay(); diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 7a0c3c00c3..360eb3261d 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -14,6 +14,11 @@ #include #include +#include "qapplication.h" + +#include "gpu/Context.h" +#include "gpu/StandardShaderLib.h" + ImageOverlay::ImageOverlay() : _imageURL(), _renderImage(false), @@ -57,15 +62,42 @@ void ImageOverlay::render(RenderArgs* args) { return; } + // TODO: I commented all the code needed to migrate this ImageOverlay rendering from naked gl to gpu::Batch + /*gpu::Batch localBatch; + gpu::Batch& batch = (args->_batch ? (*args->_batch) : localBatch); + static gpu::PipelinePointer drawPipeline; + static int texcoordRectLoc = -1; + static int colorLoc = -1; + if (!drawPipeline) { + auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS, gpu::StandardShaderLib::getDrawColoredTexturePS); + gpu::Shader::makeProgram(*blitProgram); + texcoordRectLoc = blitProgram->getUniforms().findLocation("texcoordRect"); + colorLoc = blitProgram->getUniforms().findLocation("color"); + + gpu::StatePointer blitState = gpu::StatePointer(new gpu::State()); + blitState->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + blitState->setColorWriteMask(true, true, true, true); + drawPipeline = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState)); + } + */ + // TODO: batch.setPipeline(drawPipeline); + glUseProgram(0); + if (_renderImage) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, _texture->getID()); - } + // TODO: batch.setResourceTexture(0, _texture->getGPUTexture()); + } // TODO: else { + // TODO: batch.setResourceTexture(0, args->_whiteTexture); + // TODO: } + + // TODO: batch.setViewTransform(Transform()); const float MAX_COLOR = 255.0f; xColor color = getColor(); float alpha = getAlpha(); glm::vec4 quadColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); + // TODO: batch._glUniform4fv(colorLoc, 1, (const float*) &quadColor); int left = _bounds.left(); int right = _bounds.right() + 1; @@ -75,6 +107,12 @@ void ImageOverlay::render(RenderArgs* args) { glm::vec2 topLeft(left, top); glm::vec2 bottomRight(right, bottom); + // TODO: Transform model; + // TODO: model.setTranslation(glm::vec3(0.5f * (right + left), 0.5f * (top + bottom), 0.0f)); + // TODO: model.setScale(glm::vec3(0.5f * (right - left), 0.5f * (bottom - top), 1.0f)); + // TODO: batch.setModelTransform(model); + + // if for some reason our image is not over 0 width or height, don't attempt to render the image if (_renderImage) { float imageWidth = _texture->getWidth(); @@ -104,15 +142,24 @@ void ImageOverlay::render(RenderArgs* args) { glm::vec2 texCoordTopLeft(x, y); glm::vec2 texCoordBottomRight(x + w, y + h); + glm::vec4 texcoordRect(texCoordTopLeft, w, h); + // TODO: batch._glUniform4fv(texcoordRectLoc, 1, (const float*) &texcoordRect); + // TODO: batch.draw(gpu::TRIANGLE_STRIP, 4); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); } else { + // TODO: batch.draw(gpu::TRIANGLE_STRIP, 4); DependencyManager::get()->renderQuad(topLeft, bottomRight, quadColor); } glDisable(GL_TEXTURE_2D); } else { + // TODO: batch.draw(gpu::TRIANGLE_STRIP, 4); DependencyManager::get()->renderQuad(topLeft, bottomRight, quadColor); } + + // TODO: if (!args->_batch) { + // TODO: args->_context->render(batch); + // TODO: } } void ImageOverlay::setProperties(const QScriptValue& properties) { diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index db1bc2185a..94d8bd17ca 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -115,7 +115,10 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { thisOverlay->render(renderArgs); } } - gpu::GLBackend::renderBatch(batch, true); + + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); +// gpu::GLBackend::renderBatch(batch, true); } unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { diff --git a/libraries/gpu/src/gpu/DrawColoredTexture.slf b/libraries/gpu/src/gpu/DrawColoredTexture.slf new file mode 100755 index 0000000000..b60c7d9575 --- /dev/null +++ b/libraries/gpu/src/gpu/DrawColoredTexture.slf @@ -0,0 +1,22 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Draw texture 0 fetched at texcoord.xy, Blend with color uniform +// +// Created by Sam Gateau on 7/12/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +uniform sampler2D colorMap; +uniform vec4 color; + +varying vec2 varTexcoord; + +void main(void) { + gl_FragColor = texture2D(colorMap, varTexcoord) * color; +} diff --git a/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv b/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv new file mode 100755 index 0000000000..284f68dd93 --- /dev/null +++ b/libraries/gpu/src/gpu/DrawTexcoordRectTransformUnitQuad.slv @@ -0,0 +1,39 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Draw and transform the unit quad [-1,-1 -> 1,1] +// Transform the normalized texcoords [0, 1] to be in the range [texcoordRect.xy, texcoordRect.xy + texcoordRect.zw] +// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed +// +// Created by Sam Gateau on 6/22/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +uniform vec4 texcoordRect; + +varying vec2 varTexcoord; + +void main(void) { + const vec4 UNIT_QUAD[4] = vec4[4]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) + ); + vec4 pos = UNIT_QUAD[gl_VertexID]; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + varTexcoord = ((pos.xy + 1) * 0.5) * texcoordRect.zw + texcoordRect.xy; +} diff --git a/libraries/gpu/src/gpu/StandardShaderLib.cpp b/libraries/gpu/src/gpu/StandardShaderLib.cpp index 581ce47cde..dabeeaf770 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.cpp +++ b/libraries/gpu/src/gpu/StandardShaderLib.cpp @@ -13,14 +13,46 @@ #include "StandardShaderLib.h" #include "DrawTransformUnitQuad_vert.h" +#include "DrawTexcoordRectTransformUnitQuad_vert.h" #include "DrawViewportQuadTransformTexcoord_vert.h" #include "DrawTexture_frag.h" +#include "DrawColoredTexture_frag.h" using namespace gpu; ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS; +ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS; ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS; ShaderPointer StandardShaderLib::_drawTexturePS; +ShaderPointer StandardShaderLib::_drawColoredTexturePS; +StandardShaderLib::ProgramMap StandardShaderLib::_programs; + +ShaderPointer StandardShaderLib::getProgram(GetShader getVS, GetShader getPS) { + + auto& programIt = _programs.find(std::pair(getVS, getPS)); + if (programIt != _programs.end()) { + return (*programIt).second; + } else { + auto vs = getVS(); + auto ps = getPS(); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + if (program) { + // Program created, let's try to make it + if (gpu::Shader::makeProgram((*program))) { + // All good, backup and return that program + _programs.insert(ProgramMap::value_type(std::pair(getVS, getPS), program)); + return program; + } else { + // Failed to make the program probably because vs and ps cannot work together? + } + } else { + // Failed to create the program maybe because ps and vs are not true vertex and pixel shaders? + } + } + return ShaderPointer(); +} + + ShaderPointer StandardShaderLib::getDrawTransformUnitQuadVS() { if (!_drawTransformUnitQuadVS) { @@ -29,6 +61,13 @@ ShaderPointer StandardShaderLib::getDrawTransformUnitQuadVS() { return _drawTransformUnitQuadVS; } +ShaderPointer StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS() { + if (!_drawTexcoordRectTransformUnitQuadVS) { + _drawTexcoordRectTransformUnitQuadVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(DrawTexcoordRectTransformUnitQuad_vert))); + } + return _drawTexcoordRectTransformUnitQuadVS; +} + ShaderPointer StandardShaderLib::getDrawViewportQuadTransformTexcoordVS() { if (!_drawViewportQuadTransformTexcoordVS) { _drawViewportQuadTransformTexcoordVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(DrawViewportQuadTransformTexcoord_vert))); @@ -42,3 +81,10 @@ ShaderPointer StandardShaderLib::getDrawTexturePS() { } return _drawTexturePS; } + +ShaderPointer StandardShaderLib::getDrawColoredTexturePS() { + if (!_drawColoredTexturePS) { + _drawColoredTexturePS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(DrawColoredTexture_frag))); + } + return _drawColoredTexturePS; +} diff --git a/libraries/gpu/src/gpu/StandardShaderLib.h b/libraries/gpu/src/gpu/StandardShaderLib.h index a8fc5126f8..653c4ab120 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.h +++ b/libraries/gpu/src/gpu/StandardShaderLib.h @@ -14,6 +14,7 @@ #define hifi_gpu_StandardShaderLib_h #include +#include #include "Shader.h" @@ -26,16 +27,30 @@ public: // A texcoord attribute is also generated texcoord = [(0,0),(1,1)] static ShaderPointer getDrawTransformUnitQuadVS(); + // Shader draw the unit quad objectPos = ([(-1,-1),(1,1)]) and transform it by the full model transform stack (Model, View, Proj). + // A texcoord attribute is also generated covering a rect defined from the uniform vec4 texcoordRect: texcoord = [texcoordRect.xy,texcoordRect.xy + texcoordRect.zw] + static ShaderPointer getDrawTexcoordRectTransformUnitQuadVS(); + // Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and transform the texcoord = [(0,0),(1,1)] by the model transform. static ShaderPointer getDrawViewportQuadTransformTexcoordVS(); static ShaderPointer getDrawTexturePS(); + static ShaderPointer getDrawColoredTexturePS(); + + // The shader program combining the shaders available above, so they are unique + typedef ShaderPointer (*StandardShaderLib::GetShader) (); + static ShaderPointer getProgram(GetShader vs, GetShader ps); protected: static ShaderPointer _drawTransformUnitQuadVS; + static ShaderPointer _drawTexcoordRectTransformUnitQuadVS; static ShaderPointer _drawViewportQuadTransformTexcoordVS; static ShaderPointer _drawTexturePS; + static ShaderPointer _drawColoredTexturePS; + + typedef std::map, ShaderPointer> ProgramMap; + static ProgramMap _programs; }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 5d4a7adea8..4c321f8fd9 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -114,9 +114,9 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); { - auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); - auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(VSFS, PSBlit)); + //auto VSFS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + //auto PSBlit = gpu::StandardShaderLib::getDrawTexturePS(); + auto blitProgram = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS, gpu::StandardShaderLib::getDrawTexturePS); gpu::Shader::makeProgram(*blitProgram); gpu::StatePointer blitState = gpu::StatePointer(new gpu::State()); blitState->setBlendFunction(true,