mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-22 03:40:49 +00:00
get rid of sphericalscreenshot class
This commit is contained in:
parent
226fb9c26b
commit
af38d3a47d
@ -627,161 +627,12 @@ namespace MWRender
|
|||||||
mutable bool mDone;
|
mutable bool mDone;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SphericalScreenshot
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MAPPING_SPHERICAL = 0,
|
|
||||||
MAPPING_CYLINDRICAL,
|
|
||||||
MAPPING_SMALL_PLANET,
|
|
||||||
MAPPING_CUBEMAP
|
|
||||||
} SphericalScreenshotMapping;
|
|
||||||
|
|
||||||
SphericalScreenshot(int size)
|
|
||||||
{
|
|
||||||
mSize = size;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
mImages.push_back(new osg::Image);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Image *getImage(int index)
|
|
||||||
{
|
|
||||||
return mImages[index].get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void create(osg::Image *dest, int w, int h, SphericalScreenshotMapping mapping)
|
|
||||||
{
|
|
||||||
if (mapping == MAPPING_CUBEMAP)
|
|
||||||
{
|
|
||||||
dest->allocateImage(mSize * 6,mSize,mImages[0]->r(),mImages[0]->getPixelFormat(),mImages[0]->getDataType());
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
osg::copyImage(mImages[i].get(),0,0,0,mImages[i]->s(),mImages[i]->t(),mImages[i]->r(),dest,i * mSize,0,0);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest->allocateImage(w,h,mImages[0]->r(),mImages[0]->getPixelFormat(),mImages[0]->getDataType());
|
|
||||||
|
|
||||||
for (int j = 0; j < h; ++j)
|
|
||||||
for (int i = 0; i < w; ++i)
|
|
||||||
{
|
|
||||||
osg::Vec3d coords;
|
|
||||||
osg::Vec2d normalizedXY = osg::Vec2d(i / ((float) w), j / ((float) h));
|
|
||||||
|
|
||||||
switch (mapping)
|
|
||||||
{
|
|
||||||
case MAPPING_CYLINDRICAL: coords = cylindricalCoords(normalizedXY.x(),normalizedXY.y()); break;
|
|
||||||
case MAPPING_SPHERICAL: coords = sphericalCoords(normalizedXY.x(),normalizedXY.y()); break;
|
|
||||||
case MAPPING_SMALL_PLANET: coords = smallPlanetCoords(normalizedXY.x(),normalizedXY.y()); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest->setColor(getColorByDirection(coords),i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3d cylindricalCoords(double x, double y)
|
|
||||||
{
|
|
||||||
osg::Vec3 result = osg::Vec3d(cos(-1 * x * 2 * osg::PI),sin(-1 * x * 2 * osg::PI),y * 2.0 - 1.0);
|
|
||||||
result.normalize();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3d sphericalCoords(double x, double y)
|
|
||||||
{
|
|
||||||
x = -1 * x * 2 * osg::PI;
|
|
||||||
y = (y - 0.5) * osg::PI;
|
|
||||||
|
|
||||||
osg::Vec3 result = osg::Vec3(0.0,cos(y),sin(y));
|
|
||||||
result = osg::Vec3(cos(x) * result.y(),sin(x) * result.y(),result.z());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3d smallPlanetCoords(double x, double y)
|
|
||||||
{
|
|
||||||
osg::Vec2d fromCenter = osg::Vec2d(x,y) - osg::Vec2d(0.5,0.5);
|
|
||||||
|
|
||||||
double magnitude = fromCenter.length();
|
|
||||||
|
|
||||||
fromCenter.normalize();
|
|
||||||
double dot = fromCenter * osg::Vec2d(0.0,1.0);
|
|
||||||
|
|
||||||
x = x > 0.5 ? 0.5 - (dot + 1) / 4.0 : 0.5 + (dot + 1) / 4.0;
|
|
||||||
y = pow(std::min(1.0,magnitude / 0.5),0.5);
|
|
||||||
|
|
||||||
return sphericalCoords(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec4 getColorByDirection(osg::Vec3d d)
|
|
||||||
{
|
|
||||||
// for details see OpenGL 4.4 specification page 225
|
|
||||||
|
|
||||||
double x, y;
|
|
||||||
double ma;
|
|
||||||
int side;
|
|
||||||
|
|
||||||
double ax, ay, az;
|
|
||||||
ax = fabs(d.x());
|
|
||||||
ay = fabs(d.y());
|
|
||||||
az = fabs(d.z());
|
|
||||||
|
|
||||||
if (ax > ay)
|
|
||||||
if (ax > az)
|
|
||||||
{
|
|
||||||
side = d.x() > 0 ? 1 : 3;
|
|
||||||
ma = ax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
side = d.z() > 0 ? 5 : 4;
|
|
||||||
ma = az;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (ay > az)
|
|
||||||
{
|
|
||||||
side = d.y() > 0 ? 0 : 2;
|
|
||||||
ma = ay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
side = d.z() > 0 ? 5 : 4;
|
|
||||||
ma = az;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (side)
|
|
||||||
{
|
|
||||||
case 0: x = d.x(); y = d.z(); break;
|
|
||||||
case 1: x = -d.y(); y = d.z(); break;
|
|
||||||
case 2: x = -d.x(); y = d.z(); break;
|
|
||||||
case 3: x = d.y(); y = d.z(); break;
|
|
||||||
case 4: x = d.x(); y = d.y(); break;
|
|
||||||
case 5: x = d.x(); y = -d.y(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = 0.5 * (x / ma + 1);
|
|
||||||
y = 0.5 * (y / ma + 1);
|
|
||||||
|
|
||||||
return mImages[side]->getColor(
|
|
||||||
std::min(std::max(int(x * mSize),0),mSize - 1),
|
|
||||||
std::min(std::max(int(y * mSize),0),mSize - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<osg::ref_ptr<osg::Image>> mImages;
|
|
||||||
int mSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool RenderingManager::screenshot360(osg::Image* image, std::string settingStr)
|
bool RenderingManager::screenshot360(osg::Image* image, std::string settingStr)
|
||||||
{
|
{
|
||||||
int screenshotW = mViewer->getCamera()->getViewport()->width();
|
int screenshotW = mViewer->getCamera()->getViewport()->width();
|
||||||
int screenshotH = mViewer->getCamera()->getViewport()->height();
|
int screenshotH = mViewer->getCamera()->getViewport()->height();
|
||||||
SphericalScreenshot::SphericalScreenshotMapping screenshotMapping = SphericalScreenshot::MAPPING_SPHERICAL;
|
int screenshotMapping = 0;
|
||||||
int cubeSize = screenshotMapping == SphericalScreenshot::SphericalScreenshotMapping::MAPPING_SMALL_PLANET ?
|
int cubeSize = screenshotMapping == 2 ?
|
||||||
screenshotW: // planet mapping needs higher resolution
|
screenshotW: // planet mapping needs higher resolution
|
||||||
screenshotW / 2;
|
screenshotW / 2;
|
||||||
|
|
||||||
@ -796,7 +647,7 @@ namespace MWRender
|
|||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
if (settingArgs[0].compare(typeStrings[i]) == 0)
|
if (settingArgs[0].compare(typeStrings[i]) == 0)
|
||||||
{
|
{
|
||||||
screenshotMapping = (SphericalScreenshot::SphericalScreenshotMapping) i;
|
screenshotMapping = i;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -823,16 +674,23 @@ namespace MWRender
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screenshotMapping == SphericalScreenshot::MAPPING_CUBEMAP)
|
bool rawCubemap = screenshotMapping == 3;
|
||||||
screenshotW = cubeSize * 6; // the image will consist of 6 cube sides in a row
|
|
||||||
|
|
||||||
SphericalScreenshot s(cubeSize);
|
if (rawCubemap)
|
||||||
|
screenshotW = cubeSize * 6; // the image will consist of 6 cube sides in a row
|
||||||
|
else if (screenshotMapping == 2)
|
||||||
|
screenshotH = screenshotW; // use square resolution for planet mapping
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<osg::Image>> images;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
images.push_back(new osg::Image);
|
||||||
|
|
||||||
osg::Vec3 directions[6] = {
|
osg::Vec3 directions[6] = {
|
||||||
osg::Vec3(0,0,1),
|
rawCubemap ? osg::Vec3(1,0,0) : osg::Vec3(0,0,1),
|
||||||
osg::Vec3(0,0,-1),
|
osg::Vec3(0,0,-1),
|
||||||
osg::Vec3(-1,0,0),
|
osg::Vec3(-1,0,0),
|
||||||
osg::Vec3(1,0,0),
|
rawCubemap ? osg::Vec3(0,0,1) : osg::Vec3(1,0,0),
|
||||||
osg::Vec3(0,1,0),
|
osg::Vec3(0,1,0),
|
||||||
osg::Vec3(0,-1,0)};
|
osg::Vec3(0,-1,0)};
|
||||||
|
|
||||||
@ -854,24 +712,40 @@ namespace MWRender
|
|||||||
|
|
||||||
for (int i = 0; i < 6; i++) // for each cubemap side
|
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::Matrixd transform = osg::Matrixd::rotate(osg::Vec3(0,0,-1),directions[i]);
|
||||||
osg::Image *sideImage = s.getImage(i);
|
|
||||||
screenshot(sideImage,cubeSize,cubeSize,transform);
|
|
||||||
sideImage->flipHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// s.create(image,screenshotW,screenshotMapping != SphericalScreenshot::MAPPING_SMALL_PLANET ? screenshotH : screenshotW,screenshotMapping);
|
if (!rawCubemap)
|
||||||
|
transform *= osg::Matrixd::rotate(rotations[i],osg::Vec3(0,0,-1));
|
||||||
|
|
||||||
|
osg::Image *sideImage = images[i].get();
|
||||||
|
screenshot(sideImage,cubeSize,cubeSize,transform);
|
||||||
|
|
||||||
|
if (!rawCubemap)
|
||||||
|
sideImage->flipHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
mPlayerAnimation->getObjectRoot()->setNodeMask(maskBackup);
|
mPlayerAnimation->getObjectRoot()->setNodeMask(maskBackup);
|
||||||
mFieldOfView = fovBackup;
|
mFieldOfView = fovBackup;
|
||||||
|
|
||||||
|
if (rawCubemap) // for raw cubemap don't run on GPU, just merge the images
|
||||||
|
{
|
||||||
|
image->allocateImage(cubeSize * 6,cubeSize,images[0]->r(),images[0]->getPixelFormat(),images[0]->getDataType());
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
osg::copyImage(images[i].get(),0,0,0,images[i]->s(),images[i]->t(),images[i]->r(),image,i * cubeSize,0,0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run on GPU now:
|
||||||
|
|
||||||
osg::ref_ptr<osg::TextureCubeMap> cubeTexture (new osg::TextureCubeMap);
|
osg::ref_ptr<osg::TextureCubeMap> cubeTexture (new osg::TextureCubeMap);
|
||||||
|
|
||||||
|
cubeTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||||
|
cubeTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
cubeTexture->setImage(i,s.getImage(i));
|
cubeTexture->setImage(i,images[i].get());
|
||||||
|
|
||||||
osg::ref_ptr<osg::Camera> screenshotCamera (new osg::Camera);
|
osg::ref_ptr<osg::Camera> screenshotCamera (new osg::Camera);
|
||||||
osg::ref_ptr<osg::ShapeDrawable> quad (new osg::ShapeDrawable(new osg::Box(osg::Vec3(0,0,0),2.0)));
|
osg::ref_ptr<osg::ShapeDrawable> quad (new osg::ShapeDrawable(new osg::Box(osg::Vec3(0,0,0),2.0)));
|
||||||
@ -889,6 +763,7 @@ namespace MWRender
|
|||||||
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||||
|
|
||||||
stateset->addUniform(new osg::Uniform("cubeMap",0));
|
stateset->addUniform(new osg::Uniform("cubeMap",0));
|
||||||
|
stateset->addUniform(new osg::Uniform("mapping",screenshotMapping));
|
||||||
stateset->setTextureAttributeAndModes(0,cubeTexture,osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(0,cubeTexture,osg::StateAttribute::ON);
|
||||||
|
|
||||||
quad->setStateSet(stateset);
|
quad->setStateSet(stateset);
|
||||||
@ -898,13 +773,11 @@ namespace MWRender
|
|||||||
|
|
||||||
mRootNode->addChild(screenshotCamera);
|
mRootNode->addChild(screenshotCamera);
|
||||||
|
|
||||||
renderCameraToImage(screenshotCamera,image,1000,640);
|
renderCameraToImage(screenshotCamera,image,screenshotW,screenshotH);
|
||||||
|
|
||||||
|
|
||||||
screenshotCamera->removeChildren(0,screenshotCamera->getNumChildren());
|
screenshotCamera->removeChildren(0,screenshotCamera->getNumChildren());
|
||||||
mRootNode->removeChild(screenshotCamera);
|
mRootNode->removeChild(screenshotCamera);
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,52 @@
|
|||||||
|
|
||||||
varying vec2 uv;
|
varying vec2 uv;
|
||||||
uniform samplerCube cubeMap;
|
uniform samplerCube cubeMap;
|
||||||
|
uniform int mapping;
|
||||||
|
|
||||||
#define PI 3.1415926535
|
#define PI 3.1415926535
|
||||||
|
|
||||||
|
vec3 sphericalCoords(vec2 coords)
|
||||||
|
{
|
||||||
|
coords.x = -1 * coords.x * 2 * PI;
|
||||||
|
coords.y = (coords.y - 0.5) * PI;
|
||||||
|
|
||||||
|
vec3 result = vec3(0.0,cos(coords.y),sin(coords.y));
|
||||||
|
result = vec3(cos(coords.x) * result.y,sin(coords.x) * result.y,result.z);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
vec3 cylindricalCoords(vec2 coords)
|
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));
|
return normalize(vec3(cos(-1 * coords.x * 2 * PI),sin(-1 * coords.x * 2 * PI),coords.y * 2.0 - 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 planetCoords(vec2 coords)
|
||||||
|
{
|
||||||
|
vec2 fromCenter = coords - vec2(0.5,0.5);
|
||||||
|
|
||||||
|
float magnitude = length(fromCenter);
|
||||||
|
|
||||||
|
fromCenter = normalize(fromCenter);
|
||||||
|
|
||||||
|
float dotProduct = dot(fromCenter,vec2(0.0,1.0));
|
||||||
|
|
||||||
|
coords.x = coords.x > 0.5 ? 0.5 - (dotProduct + 1.0) / 4.0 : 0.5 + (dotProduct + 1.0) / 4.0;
|
||||||
|
coords.y = max(0.0,1.0 - pow(magnitude / 0.5,0.5));
|
||||||
|
return sphericalCoords(coords);
|
||||||
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec3 c;
|
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)));
|
switch (mapping)
|
||||||
|
{
|
||||||
|
case 0: c = sphericalCoords(uv); break;
|
||||||
|
case 1: c = cylindricalCoords(uv); break;
|
||||||
|
case 2: c = planetCoords(uv); break;
|
||||||
|
default: c = sphericalCoords(uv); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragData[0] = textureCube(cubeMap,c);
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@ varying vec2 uv;
|
|||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
gl_Position = gl_Vertex;
|
gl_Position = gl_Vertex;
|
||||||
uv = (gl_Vertex.xy * vec2(1.0,-1.0) + vec2(1.0)) / 2.0;
|
uv = (gl_Vertex.xy * vec2(1.0,-1.0) + vec2(1.0)) / 2;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user