From 226fb9c26bdbbcb7a406f3ca874319d0eb4a7119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Wed, 15 Nov 2017 16:07:01 +0100 Subject: [PATCH] render cubemaps in OGL coordinates --- apps/openmw/mwrender/renderingmanager.cpp | 85 ++++++++++++----------- apps/openmw/mwrender/renderingmanager.hpp | 2 +- files/shaders/s360_fragment.glsl | 14 +++- files/shaders/s360_vertex.glsl | 2 +- 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 878056955..bb7fbd5de 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -829,13 +829,20 @@ namespace MWRender SphericalScreenshot s(cubeSize); osg::Vec3 directions[6] = { - osg::Vec3(0,0,-1), - osg::Vec3(-1,0,0), - osg::Vec3(0,0,1), - osg::Vec3(1,0,0), - osg::Vec3(0,1,0), - osg::Vec3(0,-1,0), - }; + osg::Vec3(0,0,1), + osg::Vec3(0,0,-1), + osg::Vec3(-1,0,0), + osg::Vec3(1,0,0), + osg::Vec3(0,1,0), + osg::Vec3(0,-1,0)}; + + double rotations[] = { + -osg::PI / 2.0, + osg::PI / 2.0, + osg::PI, + 0, + osg::PI / 2.0, + osg::PI / 2.0}; double fovBackup = mFieldOfView; mFieldOfView = 90.0; // each cubemap side sees 90 degrees @@ -847,51 +854,55 @@ namespace MWRender for (int i = 0; i < 6; i++) // for each cubemap side { + osg::Matrixd transform = osg::Matrixd::rotate(osg::Vec3(0,0,-1),directions[i]) * osg::Matrixd::rotate(rotations[i],osg::Vec3(0,0,-1)); osg::Image *sideImage = s.getImage(i); - screenshot(sideImage,cubeSize,cubeSize,directions[i]); + screenshot(sideImage,cubeSize,cubeSize,transform); + sideImage->flipHorizontal(); } - s.create(image,screenshotW,screenshotMapping != SphericalScreenshot::MAPPING_SMALL_PLANET ? screenshotH : screenshotW,screenshotMapping); +// s.create(image,screenshotW,screenshotMapping != SphericalScreenshot::MAPPING_SMALL_PLANET ? screenshotH : screenshotW,screenshotMapping); mPlayerAnimation->getObjectRoot()->setNodeMask(maskBackup); mFieldOfView = fovBackup; -osg::ref_ptr cubeTexture (new osg::TextureCubeMap); -for (int i = 0; i < 6; ++i) - cubeTexture->setImage(i,s.getImage(i)); -osg::ref_ptr screenshotCamera (new osg::Camera); -osg::ref_ptr quad (new osg::ShapeDrawable(new osg::Box(osg::Vec3(0,0,0),2.0))); + osg::ref_ptr cubeTexture (new osg::TextureCubeMap); -std::map defineMap; + for (int i = 0; i < 6; ++i) + cubeTexture->setImage(i,s.getImage(i)); -Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager(); -osg::ref_ptr fragmentShader (shaderMgr.getShader("s360_fragment.glsl",defineMap,osg::Shader::FRAGMENT)); -osg::ref_ptr vertexShader (shaderMgr.getShader("s360_vertex.glsl", defineMap, osg::Shader::VERTEX)); -osg::ref_ptr stateset = new osg::StateSet; + osg::ref_ptr screenshotCamera (new osg::Camera); + osg::ref_ptr quad (new osg::ShapeDrawable(new osg::Box(osg::Vec3(0,0,0),2.0))); -osg::ref_ptr program (new osg::Program); -program->addShader(fragmentShader); -program->addShader(vertexShader); -stateset->setAttributeAndModes(program, osg::StateAttribute::ON); + std::map defineMap; -stateset->addUniform(new osg::Uniform("cubeMap",0)); -stateset->setTextureAttributeAndModes(0,cubeTexture,osg::StateAttribute::ON); - -quad->setStateSet(stateset); -quad->setUpdateCallback(NULL); + Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager(); + osg::ref_ptr fragmentShader (shaderMgr.getShader("s360_fragment.glsl",defineMap,osg::Shader::FRAGMENT)); + osg::ref_ptr vertexShader (shaderMgr.getShader("s360_vertex.glsl", defineMap, osg::Shader::VERTEX)); + osg::ref_ptr stateset = new osg::StateSet; + + osg::ref_ptr program (new osg::Program); + program->addShader(fragmentShader); + program->addShader(vertexShader); + stateset->setAttributeAndModes(program, osg::StateAttribute::ON); + + stateset->addUniform(new osg::Uniform("cubeMap",0)); + stateset->setTextureAttributeAndModes(0,cubeTexture,osg::StateAttribute::ON); + + quad->setStateSet(stateset); + quad->setUpdateCallback(NULL); -screenshotCamera->addChild(quad); + screenshotCamera->addChild(quad); -mRootNode->addChild(screenshotCamera); + mRootNode->addChild(screenshotCamera); -renderCameraToImage(screenshotCamera,image,1000,640); + renderCameraToImage(screenshotCamera,image,1000,640); -screenshotCamera->removeChildren(0,screenshotCamera->getNumChildren()); -mRootNode->removeChild(screenshotCamera); + screenshotCamera->removeChildren(0,screenshotCamera->getNumChildren()); + mRootNode->removeChild(screenshotCamera); return true; @@ -936,20 +947,16 @@ mRootNode->removeChild(screenshotCamera); mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); } - void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Vec3 direction) + void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Matrixd cameraTransform) { osg::ref_ptr rttCamera (new osg::Camera); - - rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); - rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix() * osg::Matrixd::rotate(osg::Vec3(0,0,-1),direction)); - rttCamera->setNodeMask(Mask_RenderToTexture); rttCamera->attach(osg::Camera::COLOR_BUFFER, image); rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); - rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix() * osg::Matrixd::rotate(osg::Vec3(0,0,-1),direction)); + rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix() * cameraTransform); rttCamera->setViewport(0, 0, w, h); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index e6dfd3999..8fd96cff9 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -126,7 +126,7 @@ namespace MWRender void setWaterHeight(float level); /// Take a screenshot of w*h onto the given image, not including the GUI. - void screenshot(osg::Image* image, int w, int h, osg::Vec3 direction=osg::Vec3(0,0,-1)); + void screenshot(osg::Image* image, int w, int h, osg::Matrixd cameraTransform=osg::Matrixd()); bool screenshot360(osg::Image* image, std::string settingStr); struct RayResult diff --git a/files/shaders/s360_fragment.glsl b/files/shaders/s360_fragment.glsl index 4bf91abb3..3ff8e93c1 100644 --- a/files/shaders/s360_fragment.glsl +++ b/files/shaders/s360_fragment.glsl @@ -3,7 +3,19 @@ varying vec2 uv; uniform samplerCube cubeMap; +#define PI 3.1415926535 + +vec3 cylindricalCoords(vec2 coords) +{ + return normalize(vec3(cos(-1 * coords.x * 2 * PI),sin(-1 * coords.x * 2 * PI),coords.y * 2.0 - 1.0)); +} + void main(void) { - gl_FragData[0] = textureCube(cubeMap,vec3(uv.x * 2.0 - 1.0,uv.y * 2.0 - 1.0,1)); + vec3 c; + c.x = uv.x * 2.0 - 1.0; + c.y = uv.y * 2.0 - 1.0; + c.z = 1.0; + + gl_FragData[0] = textureCube(cubeMap,vec3(cylindricalCoords(uv))); } diff --git a/files/shaders/s360_vertex.glsl b/files/shaders/s360_vertex.glsl index 84cecfdaf..b7fbf28a4 100644 --- a/files/shaders/s360_vertex.glsl +++ b/files/shaders/s360_vertex.glsl @@ -5,5 +5,5 @@ varying vec2 uv; void main(void) { gl_Position = gl_Vertex; - uv = (gl_Vertex.xy + vec2(1.0)) / 2.0; + uv = (gl_Vertex.xy * vec2(1.0,-1.0) + vec2(1.0)) / 2.0; }