1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0025556: Visualization - support stereo pair formats recognized by consumer display devices

Graphic3d_StereoMode - add new enumeration for stereoscopic outputs:
- Graphic3d_StereoMode_QuadBuffer
- Graphic3d_StereoMode_Anaglyph
- Graphic3d_StereoMode_RowInterlaced
- Graphic3d_StereoMode_ColumnInterlaced
- Graphic3d_StereoMode_ChessBoard
- Graphic3d_StereoMode_SideBySide
- Graphic3d_StereoMode_OverUnder

Graphic3d_RenderingParams - add new options controlling stereo output:
- StereoMode
- ToReverseStereo
- AnaglyphFilter

OpenGl_ShaderManager - add predefined GLSL programs for new stereo outputs.
OpenGl_Workspace::Redraw() - do not implicitly disable stereo to allow stereo dump as is.
OpenGl_Caps - add flag swapInterval to control VSync.
OpenGl_Workspace::BufferDump() - handle cases with non-applicable GL_PACK_ROW_LENGTH.

CALL_DEF_WINDOW - drop unused fields; add fields "left" and "top"
to reverse stereo pair for interlaced output depending on window position.

Draw Harness, ViewerTest:
- Extend syntax of command vstereo to setup stereo.
- Extend vdump command to allow dump of stereoscopic pair in different formats.
- Extend command vcaps with option vsync.
- Use mouse scroll to zoom and adjust ZFocus in WinAPI.
- Use "/" and "*" to adjust IOD.

v3d/glsl/stereo - add test case for stereo modes.

Cocoa_LocalPool, OSD_EnvironmentIterator - fix compilation issues on OS X Snow Leopard.
This commit is contained in:
kgv 2015-06-20 16:08:12 +03:00
parent f809e94b93
commit f978241fb6
30 changed files with 1160 additions and 229 deletions

View File

@ -14,7 +14,13 @@
#ifndef __Cocoa_LocalPool_h_
#define __Cocoa_LocalPool_h_
#if defined(__clang__) && (__clang_major__ >= 4) && __has_feature(objc_arc)
#if defined(__clang__) && (__clang_major__ >= 4)
#if __has_feature(objc_arc)
#define HAVE_OBJC_ARC
#endif
#endif
#ifdef HAVE_OBJC_ARC
// @autoreleasepool should be used within ARC

View File

@ -23,9 +23,7 @@
#import <Cocoa/Cocoa.h>
#endif
#if defined(__clang__) && (__clang_major__ >= 4) && __has_feature(objc_arc)
// ARC
#else
#ifndef HAVE_OBJC_ARC
// =======================================================================
// function : Cocoa_LocalPool

View File

@ -32,10 +32,6 @@
IMPLEMENT_STANDARD_HANDLE (Cocoa_Window, Aspect_Window)
IMPLEMENT_STANDARD_RTTIEXT(Cocoa_Window, Aspect_Window)
#if defined(__clang__) && (__clang_major__ >= 4) && __has_feature(objc_arc)
#define HAVE_OBJC_ARC
#endif
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
//
#else

View File

@ -30,6 +30,7 @@ Graphic3d_ShaderProgram.cxx
Graphic3d_ShaderVariable.hxx
Graphic3d_ShaderVariable.cxx
Graphic3d_ShaderVariable.lxx
Graphic3d_StereoMode.hxx
Graphic3d_MapOfStructure.hxx
Graphic3d_MapIteratorOfMapOfStructure.hxx
Graphic3d_IndexedMapOfAddress.hxx

View File

@ -17,6 +17,9 @@
#define _Graphic3d_RenderingParams_HeaderFile
#include <Graphic3d_RenderingMode.hxx>
#include <Graphic3d_StereoMode.hxx>
#include <Graphic3d_Mat4.hxx>
#include <Graphic3d_Vec4.hxx>
//! Helper class to store rendering parameters.
class Graphic3d_RenderingParams
@ -29,51 +32,64 @@ public:
//! Default ray-tracing depth.
static const Standard_Integer THE_DEFAULT_DEPTH = 3;
//! Anaglyph filter presets.
enum Anaglyph
{
Anaglyph_RedCyan_Simple, //!< simple filter for Red-Cyan glasses (R+GB)
Anaglyph_RedCyan_Optimized, //!< optimized filter for Red-Cyan glasses (R+GB)
Anaglyph_YellowBlue_Simple, //!< simple filter for Yellow-Blue glasses (RG+B)
Anaglyph_YellowBlue_Optimized, //!< optimized filter for Yellow-Blue glasses (RG+B)
Anaglyph_GreenMagenta_Simple, //!< simple filter for Green-Magenta glasses (G+RB)
Anaglyph_UserDefined //!< use externally specified matrices
};
public:
//! Creates default rendering parameters.
Graphic3d_RenderingParams()
: Method (Graphic3d_RM_RASTERIZATION),
RaytracingDepth (THE_DEFAULT_DEPTH),
IsGlobalIlluminationEnabled (Standard_False),
SamplesPerPixel (THE_DEFAULT_SPP),
RaytracingDepth (THE_DEFAULT_DEPTH),
IsShadowEnabled (Standard_True),
IsReflectionEnabled (Standard_False),
IsAntialiasingEnabled (Standard_False),
IsTransparentShadowEnabled (Standard_False),
IsGlobalIlluminationEnabled (Standard_False),
UseEnvironmentMapBackground (Standard_False)
UseEnvironmentMapBackground (Standard_False),
StereoMode (Graphic3d_StereoMode_QuadBuffer),
AnaglyphFilter (Anaglyph_RedCyan_Optimized),
ToReverseStereo (Standard_False)
{
//
const Graphic3d_Vec4 aZero (0.0f, 0.0f, 0.0f, 0.0f);
AnaglyphLeft .SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
AnaglyphLeft .SetRow (1, aZero);
AnaglyphLeft .SetRow (2, aZero);
AnaglyphLeft .SetRow (3, aZero);
AnaglyphRight.SetRow (0, aZero);
AnaglyphRight.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
AnaglyphRight.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
AnaglyphRight.SetRow (3, aZero);
}
public:
//! Specifies rendering mode.
Graphic3d_RenderingMode Method;
Graphic3d_RenderingMode Method; //!< specifies rendering mode, Graphic3d_RM_RASTERIZATION by default
//! Maximum ray-tracing depth.
Standard_Integer RaytracingDepth;
Standard_Boolean IsGlobalIlluminationEnabled; //!< enables/disables global illumination effects (path tracing)
Standard_Integer SamplesPerPixel; //!< number of samples per pixel (SPP)
Standard_Integer RaytracingDepth; //!< maximum ray-tracing depth, 3 by default
Standard_Boolean IsShadowEnabled; //!< enables/disables shadows rendering, True by default
Standard_Boolean IsReflectionEnabled; //!< enables/disables specular reflections, False by default
Standard_Boolean IsAntialiasingEnabled; //!< enables/disables adaptive anti-aliasing, False by default
Standard_Boolean IsTransparentShadowEnabled; //!< enables/disables light propagation through transparent media, False by default
Standard_Boolean UseEnvironmentMapBackground; //!< enables/disables environment map background
//! Number of samples per pixel (SPP).
Standard_Integer SamplesPerPixel;
//! Enables/disables shadows rendering.
Standard_Boolean IsShadowEnabled;
//! Enables/disables specular reflections.
Standard_Boolean IsReflectionEnabled;
//! Enables/disables adaptive anti-aliasing.
Standard_Boolean IsAntialiasingEnabled;
//! Enables/disables light propagation through transparent media.
Standard_Boolean IsTransparentShadowEnabled;
//! Enables/disables global illumination effects (uses path tracing).
Standard_Boolean IsGlobalIlluminationEnabled;
//! Enables/disables environment map background (instead of OCCT background).
Standard_Boolean UseEnvironmentMapBackground;
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
Anaglyph AnaglyphFilter; //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default
Graphic3d_Mat4 AnaglyphLeft; //!< left anaglyph filter (in normalized colorspace), Color = AnaglyphRight * theColorRight + AnaglyphLeft * theColorLeft;
Graphic3d_Mat4 AnaglyphRight; //!< right anaglyph filter (in normalized colorspace), Color = AnaglyphRight * theColorRight + AnaglyphLeft * theColorLeft;
Standard_Boolean ToReverseStereo; //!< flag to reverse stereo pair, FALSE by default
};

View File

@ -0,0 +1,33 @@
// Created on: 2015-06-05
// Created by: Kirill Gavrilov
// Copyright (c) 2015 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Graphic3d_StereoMode_HeaderFile
#define _Graphic3d_StereoMode_HeaderFile
//! This enumeration defines the list of stereoscopic output modes.
enum Graphic3d_StereoMode
{
Graphic3d_StereoMode_QuadBuffer, //!< OpenGL QuadBuffer
Graphic3d_StereoMode_Anaglyph, //!< Anaglyph glasses, the type should be specified in addition
Graphic3d_StereoMode_RowInterlaced, //!< Row-interlaced stereo
Graphic3d_StereoMode_ColumnInterlaced, //!< Column-interlaced stereo
Graphic3d_StereoMode_ChessBoard, //!< chess-board stereo for DLP TVs
Graphic3d_StereoMode_SideBySide, //!< horizontal pair
Graphic3d_StereoMode_OverUnder, //!< vertical pair
Graphic3d_StereoMode_SoftPageFlip, //!< software PageFlip for shutter glasses, should NOT be used!
Graphic3d_StereoMode_NB //!< the number of modes
};
#endif // _Graphic3d_StereoMode_HeaderFile

View File

@ -18,10 +18,6 @@
#include <Aspect_Drawable.hxx>
#include <Aspect_RenderingContext.hxx>
typedef struct {
int mapped;
} EXT_WINDOW ;
/* WINDOW */
typedef struct {
@ -31,17 +27,8 @@ typedef struct {
Aspect_Drawable XWindow;
Aspect_Drawable XParentWindow;
EXT_WINDOW *ext_data;
struct {
float xm, ym, xM, yM;
} Position;
int dx, dy;
char *Title;
char *Icon;
int left, top;
struct {
float r, g, b;

View File

@ -21,11 +21,12 @@
//const OSD_WhoAmI Iam = OSD_WEnvironmentIterator;
#ifdef __APPLE__
#import <TargetConditionals.h>
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
extern char **environ;
#else
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
#else
extern char **environ;

View File

@ -33,6 +33,7 @@ OpenGl_Caps::OpenGl_Caps()
#else
ffpEnable (Standard_False),
#endif
swapInterval (1),
buffersNoSwap (Standard_False),
contextStereo (Standard_False),
#ifdef OCCT_DEBUG
@ -64,6 +65,7 @@ OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy)
pntSpritesDisable = theCopy.pntSpritesDisable;
keepArrayData = theCopy.keepArrayData;
ffpEnable = theCopy.ffpEnable;
swapInterval = theCopy.swapInterval;
buffersNoSwap = theCopy.buffersNoSwap;
contextStereo = theCopy.contextStereo;
contextDebug = theCopy.contextDebug;

View File

@ -31,6 +31,7 @@ public: //! @name flags to disable particular functionality, should be used only
Standard_Boolean pntSpritesDisable; //!< flag permits Point Sprites usage, will significantly affect performance (OFF by default)
Standard_Boolean keepArrayData; //!< Disables freeing CPU memory after building VBOs (OFF by default)
Standard_Boolean ffpEnable; //!< Enables FFP (fixed-function pipeline), do not use built-in GLSL programs (ON by default on desktop OpenGL and OFF on OpenGL ES)
Standard_Integer swapInterval; //!< controls swap interval - 0 for VSync off and 1 for VSync on, 1 by default
public: //! @name context creation parameters

View File

@ -45,6 +45,11 @@
//
#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
#include <dlfcn.h>
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
//
#else
#include <OpenGL/OpenGL.h>
#endif
#else
#include <GL/glx.h> // glXGetProcAddress()
#endif
@ -526,6 +531,48 @@ void OpenGl_Context::SwapBuffers()
#endif // __APPLE__
// =======================================================================
// function : SetSwapInterval
// purpose :
// =======================================================================
Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInterval)
{
#if defined(HAVE_EGL)
if (::eglSwapInterval ((EGLDisplay )myDisplay, theInterval) == EGL_TRUE)
{
return Standard_True;
}
#elif defined(_WIN32)
if (myFuncs->wglSwapIntervalEXT != NULL)
{
myFuncs->wglSwapIntervalEXT (theInterval);
return Standard_True;
}
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
//
#elif defined(__APPLE__)
if (::CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &theInterval) == kCGLNoError)
{
return Standard_True;
}
#else
if (theInterval == -1
&& myFuncs->glXSwapIntervalEXT != NULL)
{
typedef int (*glXSwapIntervalEXT_t_x)(Display* theDisplay, GLXDrawable theDrawable, int theInterval);
glXSwapIntervalEXT_t_x aFuncPtr = (glXSwapIntervalEXT_t_x )myFuncs->glXSwapIntervalEXT;
aFuncPtr ((Display* )myDisplay, (GLXDrawable )myWindow, theInterval);
return Standard_True;
}
else if (myFuncs->glXSwapIntervalSGI != NULL)
{
myFuncs->glXSwapIntervalSGI (theInterval);
return Standard_True;
}
#endif
return Standard_False;
}
// =======================================================================
// function : findProc
// purpose :
@ -1127,7 +1174,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
#define FindProcShort(theFunc) FindProc(#theFunc, myFuncs->theFunc)
// retrieve platform-dependent extensions
#if defined(_WIN32) && !defined(HAVE_EGL)
#if defined(HAVE_EGL)
//
#elif defined(_WIN32)
if (FindProcShort (wglGetExtensionsStringARB))
{
const char* aWglExts = myFuncs->wglGetExtensionsStringARB (wglGetCurrentDC());
@ -1155,6 +1204,19 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
FindProcShort (wglDXUnlockObjectsNV);
}
}
#elif defined(__APPLE__)
//
#else
const char* aGlxExts = ::glXQueryExtensionsString ((Display* )myDisplay, DefaultScreen ((Display* )myDisplay));
if (CheckExtension (aGlxExts, "GLX_EXT_swap_control"))
{
FindProcShort (glXSwapIntervalEXT);
}
if (CheckExtension (aGlxExts, "GLX_SGI_swap_control"))
{
FindProcShort (glXSwapIntervalSGI);
}
//extSwapTear = CheckExtension (aGlxExts, "GLX_EXT_swap_control_tear");
#endif
// initialize debug context extension

View File

@ -299,6 +299,9 @@ public:
|| (myGlVerMajor == theVerMajor && myGlVerMinor >= theVerMinor);
}
//! Access entire map of loaded OpenGL functions.
const OpenGl_GlFunctions* Functions() const { return myFuncs.operator->(); }
//! Clean up errors stack for this GL context (glGetError() in loop).
Standard_EXPORT void ResetErrors();
@ -314,6 +317,9 @@ public:
//! Swap front/back buffers for this GL context (should be activated before!).
Standard_EXPORT void SwapBuffers();
//! Setup swap interval (VSync).
Standard_EXPORT Standard_Boolean SetSwapInterval (const Standard_Integer theInterval);
//! Return true if active mode is GL_RENDER (cached state)
Standard_Boolean IsRender() const
{

View File

@ -310,6 +310,13 @@ Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView& t
return (aCView != NULL) && aCView->WS->BufferDump ((OpenGl_FrameBuffer* )theCView.ptrFBO, theImage, theBufferType);
}
//! Compute aligned number greater or equal to specified one
inline Standard_Size getAligned (const Standard_Size theNumber,
const Standard_Size theAlignment)
{
return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
}
Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFBOPtr,
Image_PixMap& theImage,
const Graphic3d_BufferType& theBufferType)
@ -348,14 +355,30 @@ Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFB
// setup alignment
const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
bool isBatchCopy = !theImage.IsTopDown();
const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
if (anExtraBytes < anAligment)
{
aPixelsWidth = 0;
}
else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
{
aPixelsWidth = 0;
isBatchCopy = false;
}
#if !defined(GL_ES_VERSION_2_0)
const GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
#else
if (aPixelsWidth != 0)
{
isBatchCopy = false;
}
#endif
if (theImage.IsTopDown())
if (!isBatchCopy)
{
// copy row by row
for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)

View File

@ -237,7 +237,10 @@ void OpenGl_ShaderManager::clear()
myMapOfLightPrograms.Clear();
myFontProgram.Nullify();
myBlitProgram.Nullify();
myAnaglyphProgram.Nullify();
for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
{
myStereoPrograms[aModeIter].Nullify();
}
switchLightPrograms();
}
@ -1629,10 +1632,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
}
// =======================================================================
// function : prepareStdProgramAnaglyph
// function : prepareStdProgramStereo
// purpose :
// =======================================================================
Standard_Boolean OpenGl_ShaderManager::prepareStdProgramAnaglyph()
Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
const Graphic3d_StereoMode theStereoMode)
{
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert =
@ -1643,21 +1647,188 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramAnaglyph()
EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
EOL"}";
TCollection_AsciiString aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" aColorL.b = 0.0;"
EOL" aColorL.g = 0.0;"
EOL" aColorR.r = 0.0;"
EOL" occFragColor = aColorL + aColorR;"
EOL"}";
TCollection_AsciiString aSrcFrag;
switch (theStereoMode)
{
case Graphic3d_StereoMode_Anaglyph:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"uniform mat4 uMultL;"
EOL"uniform mat4 uMultR;"
EOL
EOL"vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
EOL"vec4 THE_POW_DOWN = 1.0 / THE_POW_UP;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
EOL" aColorR = pow (aColorR, THE_POW_UP);"
EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
EOL"}";
break;
}
case Graphic3d_StereoMode_RowInterlaced:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" if (int (mod (gl_FragCoord.y + 1.5, 2.0)) == 1)"
EOL" {"
EOL" occFragColor = aColorL;"
EOL" }"
EOL" else"
EOL" {"
EOL" occFragColor = aColorR;"
EOL" }"
EOL"}";
break;
}
case Graphic3d_StereoMode_ColumnInterlaced:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" if (int (mod (gl_FragCoord.x + 1.5, 2.0)) != 1)"
EOL" {"
EOL" occFragColor = aColorL;"
EOL" }"
EOL" else"
EOL" {"
EOL" occFragColor = aColorR;"
EOL" }"
EOL"}";
break;
}
case Graphic3d_StereoMode_ChessBoard:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x + 1.5), 2.0)) == 1;"
EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y + 1.5), 2.0)) != 1;"
EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
EOL" {"
EOL" occFragColor = aColorL;"
EOL" }"
EOL" else"
EOL" {"
EOL" occFragColor = aColorR;"
EOL" }"
EOL"}";
break;
}
case Graphic3d_StereoMode_SideBySide:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
EOL" if (TexCoord.x > 0.5)"
EOL" {"
EOL" aTexCoord.x -= 1.0;"
EOL" }"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
EOL" if (TexCoord.x <= 0.5)"
EOL" {"
EOL" occFragColor = aColorL;"
EOL" }"
EOL" else"
EOL" {"
EOL" occFragColor = aColorR;"
EOL" }"
EOL"}";
break;
}
case Graphic3d_StereoMode_OverUnder:
{
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
EOL" if (TexCoord.y > 0.5)"
EOL" {"
EOL" aTexCoord.y -= 1.0;"
EOL" }"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
EOL" if (TexCoord.y <= 0.5)"
EOL" {"
EOL" occFragColor = aColorL;"
EOL" }"
EOL" else"
EOL" {"
EOL" occFragColor = aColorR;"
EOL" }"
EOL"}";
break;
}
case Graphic3d_StereoMode_QuadBuffer:
case Graphic3d_StereoMode_SoftPageFlip:
default:
{
/*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
if (!aProgram.IsNull())
{
return aProgram->IsValid();
}*/
aSrcFrag =
EOL"uniform sampler2D uLeftSampler;"
EOL"uniform sampler2D uRightSampler;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
EOL" aColorL.b = 0.0;"
EOL" aColorL.g = 0.0;"
EOL" aColorR.r = 0.0;"
EOL" occFragColor = aColorL + aColorR;"
EOL"}";
break;
}
}
#if !defined(GL_ES_VERSION_2_0)
if (myContext->core32 != NULL)
@ -1669,15 +1840,15 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramAnaglyph()
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
TCollection_AsciiString aKey;
if (!Create (aProgramSrc, aKey, myAnaglyphProgram))
if (!Create (aProgramSrc, aKey, theProgram))
{
myAnaglyphProgram = new OpenGl_ShaderProgram(); // just mark as invalid
theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
return Standard_False;
}
myContext->BindProgram (myAnaglyphProgram);
myAnaglyphProgram->SetSampler (myContext, "uLeftSampler", 0);
myAnaglyphProgram->SetSampler (myContext, "uRightSampler", 1);
myContext->BindProgram (theProgram);
theProgram->SetSampler (myContext, "uLeftSampler", 0);
theProgram->SetSampler (myContext, "uRightSampler", 1);
myContext->BindProgram (NULL);
return Standard_True;
}

View File

@ -17,6 +17,7 @@
#define _OpenGl_ShaderManager_HeaderFile
#include <Graphic3d_ShaderProgram.hxx>
#include <Graphic3d_StereoMode.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_Sequence.hxx>
@ -161,15 +162,21 @@ public:
&& myContext->BindProgram (myBlitProgram);
}
//! Bind program for rendering Anaglyph image.
Standard_Boolean BindAnaglyphProgram()
//! Bind program for rendering stereoscopic image.
Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode)
{
if (myAnaglyphProgram.IsNull())
if (theStereoMode < 0 || theStereoMode >= Graphic3d_StereoMode_NB)
{
prepareStdProgramAnaglyph();
return Standard_False;
}
return !myAnaglyphProgram.IsNull()
&& myContext->BindProgram (myAnaglyphProgram);
if (myStereoPrograms[theStereoMode].IsNull())
{
prepareStdProgramStereo (myStereoPrograms[theStereoMode], theStereoMode);
}
const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode];
return !aProgram.IsNull()
&& myContext->BindProgram (aProgram);
}
public:
@ -370,8 +377,9 @@ protected:
//! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms
Standard_EXPORT void switchLightPrograms();
//! Prepare standard GLSL program for Anaglyph image.
Standard_EXPORT Standard_Boolean prepareStdProgramAnaglyph();
//! Prepare standard GLSL program for stereoscopic image.
Standard_EXPORT Standard_Boolean prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
const Graphic3d_StereoMode theStereoMode);
protected:
@ -383,7 +391,7 @@ protected:
Handle(OpenGl_ShaderProgram) myBlitProgram; //!< standard program for FBO blit emulation
OpenGl_MapOfShaderPrograms myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration
Handle(OpenGl_ShaderProgram) myAnaglyphProgram; //!< standard program for Anaglyph image
Handle(OpenGl_ShaderProgram) myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
OpenGl_Context* myContext; //!< OpenGL context

View File

@ -141,7 +141,8 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
myOwnGContext (theGContext == 0),
myWidth (theCWindow.dx),
myHeight (theCWindow.dy),
myBgColor (THE_DEFAULT_BG_COLOR)
myBgColor (THE_DEFAULT_BG_COLOR),
mySwapInterval (theCaps->swapInterval)
{
myBgColor.rgb[0] = theCWindow.Background.r;
myBgColor.rgb[1] = theCWindow.Background.g;
@ -672,7 +673,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
#endif
myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval);
Init();
}

View File

@ -98,6 +98,8 @@ protected:
Standard_Integer myHeight; //!< window height in pixels
TEL_COLOUR myBgColor; //!< background color
Standard_Integer mySwapInterval;//!< last assigned swap interval (VSync) for this window
public:
DEFINE_STANDARD_RTTI(OpenGl_Window) // Type definition

View File

@ -74,7 +74,8 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#endif
myWidth (theCWindow.dx),
myHeight (theCWindow.dy),
myBgColor (THE_DEFAULT_BG_COLOR)
myBgColor (THE_DEFAULT_BG_COLOR),
mySwapInterval (theCaps->swapInterval)
{
myBgColor.rgb[0] = theCWindow.Background.r;
myBgColor.rgb[1] = theCWindow.Background.g;
@ -217,6 +218,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#endif
myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval);
Init();
}

View File

@ -706,6 +706,10 @@ bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
{
return false;
}
else if (theReadFbo == theDrawFbo)
{
return true;
}
// clear destination before blitting
if (theDrawFbo != NULL
@ -807,7 +811,7 @@ bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
// function : drawStereoPair
// purpose :
// =======================================================================
void OpenGl_Workspace::drawStereoPair()
void OpenGl_Workspace::drawStereoPair (const Graphic3d_CView& theCView)
{
OpenGl_FrameBuffer* aPair[2] =
{
@ -815,7 +819,8 @@ void OpenGl_Workspace::drawStereoPair()
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
};
if (aPair[0] == NULL
|| aPair[1] == NULL)
|| aPair[1] == NULL
|| !myTransientDrawToFront)
{
aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
@ -827,6 +832,27 @@ void OpenGl_Workspace::drawStereoPair()
return;
}
Standard_Boolean toReverse = theCView.RenderParams.ToReverseStereo;
const Standard_Boolean isOddY = (theCView.DefWindow.top + theCView.DefWindow.dy) % 2 == 1;
const Standard_Boolean isOddX = theCView.DefWindow.left % 2 == 1;
if (isOddY
&& (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
|| theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
{
toReverse = !toReverse;
}
if (isOddX
&& (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
|| theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
{
toReverse = !toReverse;
}
if (toReverse)
{
std::swap (aPair[0], aPair[1]);
}
myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
myGlContext->core20fwd->glDepthMask (GL_TRUE);
myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
@ -846,8 +872,71 @@ void OpenGl_Workspace::drawStereoPair()
const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
if (myFullScreenQuad.IsValid()
&& aManager->BindAnaglyphProgram())
&& aManager->BindStereoProgram (theCView.RenderParams.StereoMode))
{
if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
{
OpenGl_Mat4 aFilterL, aFilterR;
aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
switch (theCView.RenderParams.AnaglyphFilter)
{
case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
{
aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
break;
}
case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
{
aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f));
aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f));
aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f));
aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f));
aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f));
aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
break;
}
case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
{
aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
break;
}
case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
{
aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f));
aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f));
aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f));
aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f));
aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f));
aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
break;
}
case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
{
aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
break;
}
case Graphic3d_RenderingParams::Anaglyph_UserDefined:
{
aFilterL = theCView.RenderParams.AnaglyphLeft;
aFilterR = theCView.RenderParams.AnaglyphRight;
break;
}
}
myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultL", aFilterL);
myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultR", aFilterR);
}
aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0);
aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
@ -883,8 +972,17 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
return;
}
if (mySwapInterval != myGlContext->caps->swapInterval)
{
mySwapInterval = myGlContext->caps->swapInterval;
myGlContext->SetSwapInterval (mySwapInterval);
}
++myFrameCounter;
myIsCullingEnabled = theCView.IsCullingEnabled;
const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
// release pending GL resources
myGlContext->ReleaseDelayed();
@ -908,7 +1006,7 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
}
if (myHasFboBlit
&& myTransientDrawToFront)
&& (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
{
if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
|| myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
@ -933,35 +1031,29 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
myImmediateSceneFbos[1]->ChangeViewport (0, 0);
}
// draw entire frame using normal OpenGL pipeline
const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
if (aProjectType == Graphic3d_Camera::Projection_Stereo)
if (aProjectType == Graphic3d_Camera::Projection_Stereo
&& myMainSceneFbos[0]->IsValid())
{
if (aFrameBuffer != NULL
|| !myGlContext->IsRender())
myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
if (!myMainSceneFbos[1]->IsValid())
{
// implicitly switch to mono camera for image dump
// no enough memory?
aProjectType = Graphic3d_Camera::Projection_Perspective;
}
else if (myMainSceneFbos[0]->IsValid())
else if (!myTransientDrawToFront)
{
myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
if (!myMainSceneFbos[1]->IsValid())
//
}
else if (!myGlContext->HasStereoBuffers()
|| aStereoMode != Graphic3d_StereoMode_QuadBuffer)
{
myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
if (!myImmediateSceneFbos[0]->IsValid()
|| !myImmediateSceneFbos[1]->IsValid())
{
// no enough memory?
aProjectType = Graphic3d_Camera::Projection_Perspective;
}
else if (!myGlContext->HasStereoBuffers())
{
myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
if (!myImmediateSceneFbos[0]->IsValid()
|| !myImmediateSceneFbos[1]->IsValid())
{
aProjectType = Graphic3d_Camera::Projection_Perspective;
}
}
}
}
@ -978,23 +1070,40 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
};
if (!myTransientDrawToFront)
{
anImmFbos[0] = aMainFbos[0];
anImmFbos[1] = aMainFbos[1];
}
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
{
anImmFbos[0] = NULL;
anImmFbos[1] = NULL;
}
#if !defined(GL_ES_VERSION_2_0)
myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
#endif
redraw1 (theCView, theCUnderLayer, theCOverLayer,
aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
myBackBufferRestored = Standard_True;
myIsImmediateDrawn = Standard_False;
#if !defined(GL_ES_VERSION_2_0)
myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
#endif
if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[0], aProjectType, anImmFbos[0]))
{
toSwap = false;
}
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap)
{
myGlContext->SwapBuffers();
}
#if !defined(GL_ES_VERSION_2_0)
myGlContext->SetReadDrawBuffer (GL_BACK_RIGHT);
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
#endif
redraw1 (theCView, theCUnderLayer, theCOverLayer,
aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
@ -1008,7 +1117,7 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
if (anImmFbos[0] != NULL)
{
bindDefaultFbo (aFrameBuffer);
drawStereoPair();
drawStereoPair (theCView);
}
}
else
@ -1227,6 +1336,7 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
}
const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
if (aProjectType == Graphic3d_Camera::Projection_Stereo)
{
if (aFrameBuffer != NULL)
@ -1266,6 +1376,12 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
};
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
{
anImmFbos[0] = NULL;
anImmFbos[1] = NULL;
}
if (myGlContext->arbFBO != NULL)
{
@ -1274,7 +1390,7 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
#if !defined(GL_ES_VERSION_2_0)
if (anImmFbos[0] == NULL)
{
myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
}
#endif
toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
@ -1282,6 +1398,12 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
Graphic3d_Camera::Projection_MonoLeftEye,
anImmFbos[0],
Standard_True) || toSwap;
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap
&& !myGlContext->caps->buffersNoSwap)
{
myGlContext->SwapBuffers();
}
if (myGlContext->arbFBO != NULL)
{
@ -1290,7 +1412,7 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
#if !defined(GL_ES_VERSION_2_0)
if (anImmFbos[1] == NULL)
{
myGlContext->SetReadDrawBuffer (GL_BACK_RIGHT);
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
}
#endif
toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
@ -1301,7 +1423,7 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
if (anImmFbos[0] != NULL)
{
bindDefaultFbo (aFrameBuffer);
drawStereoPair();
drawStereoPair (theCView);
}
}
else

View File

@ -295,7 +295,7 @@ protected:
void bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo = NULL);
//! Blend together views pair into stereo image.
void drawStereoPair();
void drawStereoPair (const Graphic3d_CView& theCView);
//! Blit snapshot containing main scene (myMainSceneFbos or BackBuffer)
//! into presentation buffer (myMainSceneFbos -> offscreen FBO or myMainSceneFbos -> BackBuffer or BackBuffer -> FrontBuffer),

View File

@ -12,3 +12,4 @@ V3d_View_5.cxx
V3d_Plane.hxx
V3d_Plane.cxx
V3d_ListOfTransient.hxx
V3d_StereoDumpOptions.hxx

View File

@ -156,16 +156,7 @@ is
-- TOBM_ALWAYS_DISPLAYED force display of back faces
-- TOBM_NEVER_DISPLAYED disable display of back faces
enumeration StereoDumpOptions is
SDO_MONO,
SDO_LEFT_EYE,
SDO_RIGHT_EYE
end StereoDumpOptions;
---Purpose : Options to be used with image dumping.
--
-- SDO_MONO dump monographic projection for stereo camera
-- SDO_LEFT_EYE dump left eye projection for stereo camera
-- SDO_RIGHT_EYE dump right eye projection for stereo camera
primitive StereoDumpOptions;
------------------------
---Category: The classes

View File

@ -0,0 +1,29 @@
// Created on: 2015-06-05
// Created by: Kirill Gavrilov
// Copyright (c) 2015 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _V3d_StereoDumpOptions_HeaderFile
#define _V3d_StereoDumpOptions_HeaderFile
//! Options to be used with image dumping.
//! Notice that the value will have no effect with disabled stereo output.
enum V3d_StereoDumpOptions
{
V3d_SDO_MONO, //!< ignore stereo mode and dump monographic projection for stereo camera
V3d_SDO_LEFT_EYE, //!< dump only left eye projection for stereo camera
V3d_SDO_RIGHT_EYE, //!< dump only right eye projection for stereo camera
V3d_SDO_BLENDED //!< dump blended pair specific to the active device output Graphic3d_StereoMode (result will be undefined for modes like Graphic3d_StereoMode_QuadBuffer)
};
#endif // _V3d_StereoDumpOptions_HeaderFile

View File

@ -2872,17 +2872,25 @@ Standard_Boolean V3d_View::ToPixMap (Image_PixMap& theImage,
{
switch (theStereoOptions)
{
case V3d_SDO_MONO :
case V3d_SDO_MONO:
{
myCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
break;
case V3d_SDO_LEFT_EYE :
}
case V3d_SDO_LEFT_EYE:
{
myCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
break;
case V3d_SDO_RIGHT_EYE :
}
case V3d_SDO_RIGHT_EYE:
{
myCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
break;
}
case V3d_SDO_BLENDED:
{
break; // dump as is
}
}
}

View File

@ -759,6 +759,14 @@ static int VSelPrecision(Draw_Interpretor& di, Standard_Integer argc, const char
return 0;
}
//! Auxiliary enumeration
enum ViewerTest_StereoPair
{
ViewerTest_SP_Single,
ViewerTest_SP_SideBySide,
ViewerTest_SP_OverUnder
};
//==============================================================================
//function : VDump
//purpose : To dump the active view snapshot to image file
@ -777,42 +785,108 @@ static Standard_Integer VDump (Draw_Interpretor& theDI,
Standard_CString aFilePath = theArgVec[anArgIter++];
Graphic3d_BufferType aBufferType = Graphic3d_BT_RGB;
V3d_StereoDumpOptions aStereoOpts = V3d_SDO_MONO;
ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
Standard_Integer aWidth = 0;
Standard_Integer aHeight = 0;
for (; anArgIter < theArgNb; ++anArgIter)
{
TCollection_AsciiString anArg (theArgVec[anArgIter]);
anArg.LowerCase();
if (anArg == "rgba")
if (anArg == "-buffer")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
return 1;
}
TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
aBufArg.LowerCase();
if (aBufArg == "rgba")
{
aBufferType = Graphic3d_BT_RGBA;
}
else if (aBufArg == "rgb")
{
aBufferType = Graphic3d_BT_RGB;
}
else if (aBufArg == "depth")
{
aBufferType = Graphic3d_BT_Depth;
}
else
{
std::cout << "Error: unknown buffer '" << aBufArg << "'\n";
return 1;
}
}
else if (anArg == "-stereo")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
return 1;
}
TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
aStereoArg.LowerCase();
if (aStereoArg == "l"
|| aStereoArg == "left")
{
aStereoOpts = V3d_SDO_LEFT_EYE;
}
else if (aStereoArg == "r"
|| aStereoArg == "right")
{
aStereoOpts = V3d_SDO_RIGHT_EYE;
}
else if (aStereoArg == "mono")
{
aStereoOpts = V3d_SDO_MONO;
}
else if (aStereoArg == "blended"
|| aStereoArg == "blend"
|| aStereoArg == "stereo")
{
aStereoOpts = V3d_SDO_BLENDED;
}
else if (aStereoArg == "sbs"
|| aStereoArg == "sidebyside")
{
aStereoPair = ViewerTest_SP_SideBySide;
}
else if (aStereoArg == "ou"
|| aStereoArg == "overunder")
{
aStereoPair = ViewerTest_SP_OverUnder;
}
else
{
std::cout << "Error: unknown stereo format '" << aStereoArg << "'\n";
return 1;
}
}
else if (anArg == "-rgba"
|| anArg == "rgba")
{
aBufferType = Graphic3d_BT_RGBA;
}
else if (anArg == "rgb")
else if (anArg == "-rgb"
|| anArg == "rgb")
{
aBufferType = Graphic3d_BT_RGB;
}
else if (anArg == "depth")
else if (anArg == "-depth"
|| anArg == "depth")
{
aBufferType = Graphic3d_BT_Depth;
}
else if (anArg == "l"
|| anArg == "left")
else if (anArg == "-width"
|| anArg == "width"
|| anArg == "sizex")
{
aStereoOpts = V3d_SDO_LEFT_EYE;
}
else if (anArg == "r"
|| anArg == "right")
{
aStereoOpts = V3d_SDO_RIGHT_EYE;
}
else if (anArg == "mono")
{
aStereoOpts = V3d_SDO_MONO;
}
else if (anArg == "w"
|| anArg == "width")
{
if (aWidth != 0)
if (aWidth != 0)
{
std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
return 1;
@ -824,38 +898,22 @@ static Standard_Integer VDump (Draw_Interpretor& theDI,
}
aWidth = Draw::Atoi (theArgVec[anArgIter]);
}
else if (anArg == "h"
|| anArg == "height")
else if (anArg == "-height"
|| anArg == "height"
|| anArg == "-sizey")
{
if (aHeight != 0)
{
std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
return 1;
}
if (++anArgIter >= theArgNb)
else if (++anArgIter >= theArgNb)
{
std::cout << "Error: integer value is expected right after 'height'\n";
return 1;
}
aHeight = Draw::Atoi (theArgVec[anArgIter]);
}
else if (anArg.IsIntegerValue())
{
// compatibility with old syntax
if (aWidth != 0
|| aHeight != 0)
{
std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
return 1;
}
else if (++anArgIter >= theArgNb)
{
std::cout << "Error: height value is expected right after width\n";
return 1;
}
aWidth = Draw::Atoi (theArgVec[anArgIter - 1]);
aHeight = Draw::Atoi (theArgVec[anArgIter]);
}
else
{
std::cout << "Error: unknown argument '" << theArgVec[anArgIter] << "'\n";
@ -878,33 +936,82 @@ static Standard_Integer VDump (Draw_Interpretor& theDI,
if (aWidth <= 0 || aHeight <= 0)
{
if (aStereoOpts != V3d_SDO_MONO)
{
aView->Window()->Size (aWidth, aHeight);
}
else
{
if (!aView->Dump (aFilePath, aBufferType))
{
theDI << "Fail: view dump failed!\n";
}
return 0;
}
aView->Window()->Size (aWidth, aHeight);
}
Image_AlienPixMap aPixMap;
if (!aView->ToPixMap (aPixMap, aWidth, aHeight, aBufferType, Standard_True, aStereoOpts))
bool isBigEndian = Image_PixMap::IsBigEndianHost();
Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN;
switch (aBufferType)
{
theDI << "Fail: view dump failed!\n";
return 0;
case Graphic3d_BT_RGB: aFormat = isBigEndian ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR; break;
case Graphic3d_BT_RGBA: aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break;
case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break;
}
if (aPixMap.SizeX() != Standard_Size(aWidth)
|| aPixMap.SizeY() != Standard_Size(aHeight))
switch (aStereoPair)
{
theDI << "Fail: dumped dimensions " << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
<< " are lesser than requested " << aWidth << "x" << aHeight << "\n";
case ViewerTest_SP_Single:
{
if (!aView->ToPixMap (aPixMap, aWidth, aHeight, aBufferType, Standard_True, aStereoOpts))
{
theDI << "Fail: view dump failed!\n";
return 0;
}
else if (aPixMap.SizeX() != Standard_Size(aWidth)
|| aPixMap.SizeY() != Standard_Size(aHeight))
{
theDI << "Fail: dumped dimensions " << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
<< " are lesser than requested " << aWidth << "x" << aHeight << "\n";
}
break;
}
case ViewerTest_SP_SideBySide:
{
if (!aPixMap.InitZero (aFormat, aWidth * 2, aHeight))
{
theDI << "Fail: not enough memory for image allocation!\n";
return 0;
}
Image_PixMap aPixMapL, aPixMapR;
aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
aWidth, aHeight, aPixMap.SizeRowBytes());
aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aWidth,
aWidth, aHeight, aPixMap.SizeRowBytes());
if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE)
|| !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE)
)
{
theDI << "Fail: view dump failed!\n";
return 0;
}
break;
}
case ViewerTest_SP_OverUnder:
{
if (!aPixMap.InitZero (aFormat, aWidth, aHeight * 2))
{
theDI << "Fail: not enough memory for image allocation!\n";
return 0;
}
Image_PixMap aPixMapL, aPixMapR;
aPixMapL.InitWrapper (aFormat, aPixMap.ChangeData(),
aWidth, aHeight, aPixMap.SizeRowBytes());
aPixMapR.InitWrapper (aFormat, aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aHeight,
aWidth, aHeight, aPixMap.SizeRowBytes());
if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE)
|| !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE))
{
theDI << "Fail: view dump failed!\n";
return 0;
}
break;
}
}
if (!aPixMap.Save (aFilePath))
{
theDI << "Fail: image can not be saved!\n";
@ -912,7 +1019,6 @@ static Standard_Integer VDump (Draw_Interpretor& theDI,
return 0;
}
//==============================================================================
//function : Displays,Erase...
//purpose :
@ -5348,16 +5454,16 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
"Lists all objects displayed in 3D viewer",
__FILE__,VDir,group);
#ifdef HAVE_FREEIMAGE
#define DUMP_FORMATS "{png|bmp|jpg|gif}"
#else
#define DUMP_FORMATS "{ppm}"
#endif
theCommands.Add("vdump",
#ifdef HAVE_FREEIMAGE
"vdump <filename>.{png|bmp|jpg|gif} [rgb|rgba|depth=rgb] [mono|left|right=mono]"
"\n\t\t: [width Width=0 height Height=0]"
"\n\t\t: Dumps content of the active view into PNG, BMP, JPEG or GIF file",
#else
"vdump <filename>.{ppm} [rgb|rgba|depth=rgb] [mono|left|right=mono]"
"\n\t\t: [width Width=0 height Height=0]"
"\n\t\t: Dumps content of the active view into PPM image file",
#endif
"vdump <filename>." DUMP_FORMATS " [-width Width -height Height]"
"\n\t\t: [-buffer rgb|rgba|depth=rgb]"
"\n\t\t: [-stereo mono|left|right|blend|sideBySide|overUnder=mono]"
"\n\t\t: Dumps content of the active view into image file",
__FILE__,VDump,group);
theCommands.Add("vsub", "vsub 0/1 (off/on) [obj] : Subintensity(on/off) of selected objects",

View File

@ -1512,6 +1512,24 @@ void VT_ProcessKeyPress (const char* buf_ret)
{
ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
}
else if (!strcasecmp (buf_ret, "/"))
{
Handle(Graphic3d_Camera) aCamera = aView->Camera();
if (aCamera->IsStereo())
{
aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
aView->Redraw();
}
}
else if (!strcasecmp (buf_ret, "*"))
{
Handle(Graphic3d_Camera) aCamera = aView->Camera();
if (aCamera->IsStereo())
{
aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
aView->Redraw();
}
}
else if (*buf_ret == THE_KEY_DELETE)
{
Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
@ -1983,8 +2001,12 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
LPARAM lParam )
{
static int Up = 1;
const Handle(V3d_View)& aView = ViewerTest::CurrentView();
if (aView.IsNull())
{
return DefWindowProc( hwnd, Msg, wParam, lParam );
}
if ( !ViewerTest::CurrentView().IsNull() ) {
PAINTSTRUCT ps;
switch( Msg ) {
@ -1997,6 +2019,20 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
case WM_SIZE:
VT_ProcessConfigure();
break;
case WM_MOVE:
case WM_MOVING:
case WM_SIZING:
switch (aView->RenderingParams().StereoMode)
{
case Graphic3d_StereoMode_RowInterlaced:
case Graphic3d_StereoMode_ColumnInterlaced:
case Graphic3d_StereoMode_ChessBoard:
VT_ProcessConfigure(); // track window moves to reverse stereo pair
break;
default:
break;
}
break;
case WM_KEYDOWN:
if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
@ -2018,6 +2054,15 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
{
c[0] = '.';
}
else if (wParam == VK_DIVIDE)
{
c[0] = '/';
}
// dot
else if (wParam == VK_MULTIPLY)
{
c[0] = '*';
}
VT_ProcessKeyPress (c);
}
break;
@ -2059,6 +2104,29 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
}
break;
case WM_MOUSEWHEEL:
{
int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
if (wParam & MK_CONTROL)
{
if (aView->Camera()->IsStereo())
{
Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
if (aFocus > 0.2
&& aFocus < 2.0)
{
aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
aView->Redraw();
}
}
}
else
{
aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
}
break;
}
case WM_MOUSEMOVE:
{
//cout << "\t WM_MOUSEMOVE" << endl;
@ -2120,9 +2188,6 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
return( DefWindowProc( hwnd, Msg, wParam, lParam ));
}
return 0L;
}
return DefWindowProc( hwnd, Msg, wParam, lParam );
}
@ -5413,7 +5478,9 @@ static int VCaps (Draw_Interpretor& theDI,
theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
theDI << "SoftMode:" << (aCaps->contextNoAccel ? "1" : "0") << "\n";
theDI << "FFP: " << (aCaps->ffpEnable ? "1" : "0") << "\n";
theDI << "VSync: " << aCaps->swapInterval << "\n";
theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
theDI << "Stereo: " << (aCaps->contextStereo ? "1" : "0") << "\n";
return 0;
}
@ -5427,6 +5494,17 @@ static int VCaps (Draw_Interpretor& theDI,
{
continue;
}
else if (anArgCase == "-vsync"
|| anArgCase == "-swapinterval")
{
Standard_Boolean toEnable = Standard_True;
if (++anArgIter < theArgNb
&& !parseOnOff (theArgVec[anArgIter], toEnable))
{
--anArgIter;
}
aCaps->swapInterval = toEnable;
}
else if (anArgCase == "-ffp")
{
Standard_Boolean toEnable = Standard_True;
@ -5511,6 +5589,17 @@ static int VCaps (Draw_Interpretor& theDI,
aCaps->ffpEnable = Standard_False;
}
}
else if (anArgCase == "-stereo"
|| anArgCase == "-quadbuffer")
{
Standard_Boolean toEnable = Standard_True;
if (++anArgIter < theArgNb
&& !parseOnOff (theArgVec[anArgIter], toEnable))
{
--anArgIter;
}
aCaps->contextStereo = toEnable;
}
else
{
std::cout << "Error: unknown argument '" << anArg << "'\n";
@ -7301,6 +7390,94 @@ static int VCamera (Draw_Interpretor& theDI,
return 0;
}
//! Parse stereo output mode
inline Standard_Boolean parseStereoMode (Standard_CString theArg,
Graphic3d_StereoMode& theMode)
{
TCollection_AsciiString aFlag (theArg);
aFlag.LowerCase();
if (aFlag == "quadbuffer")
{
theMode = Graphic3d_StereoMode_QuadBuffer;
}
else if (aFlag == "anaglyph")
{
theMode = Graphic3d_StereoMode_Anaglyph;
}
else if (aFlag == "row"
|| aFlag == "rowinterlaced")
{
theMode = Graphic3d_StereoMode_RowInterlaced;
}
else if (aFlag == "col"
|| aFlag == "colinterlaced"
|| aFlag == "columninterlaced")
{
theMode = Graphic3d_StereoMode_ColumnInterlaced;
}
else if (aFlag == "chess"
|| aFlag == "chessboard")
{
theMode = Graphic3d_StereoMode_ChessBoard;
}
else if (aFlag == "sbs"
|| aFlag == "sidebyside")
{
theMode = Graphic3d_StereoMode_SideBySide;
}
else if (aFlag == "ou"
|| aFlag == "overunder")
{
theMode = Graphic3d_StereoMode_OverUnder;
}
else if (aFlag == "pageflip"
|| aFlag == "softpageflip")
{
theMode = Graphic3d_StereoMode_SoftPageFlip;
}
else
{
return Standard_False;
}
return Standard_True;
}
//! Parse anaglyph filter
inline Standard_Boolean parseAnaglyphFilter (Standard_CString theArg,
Graphic3d_RenderingParams::Anaglyph& theFilter)
{
TCollection_AsciiString aFlag (theArg);
aFlag.LowerCase();
if (aFlag == "redcyansimple")
{
theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
}
else if (aFlag == "redcyan"
|| aFlag == "redcyanoptimized")
{
theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
}
else if (aFlag == "yellowbluesimple")
{
theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
}
else if (aFlag == "yellowblue"
|| aFlag == "yellowblueoptimized")
{
theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
}
else if (aFlag == "greenmagenta"
|| aFlag == "greenmagentasimple")
{
theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
}
else
{
return Standard_False;
}
return Standard_True;
}
//==============================================================================
//function : VStereo
//purpose :
@ -7310,12 +7487,12 @@ static int VStereo (Draw_Interpretor& theDI,
Standard_Integer theArgNb,
const char** theArgVec)
{
Handle(V3d_View) aView = ViewerTest::CurrentView();
if (theArgNb < 2)
{
Handle(V3d_View) aView = ViewerTest::CurrentView();
if (aView.IsNull())
{
std::cerr << "No active view. Please call vinit.\n";
std::cout << "Error: no active viewer!\n";
return 0;
}
@ -7324,7 +7501,130 @@ static int VStereo (Draw_Interpretor& theDI,
return 0;
}
ViewerTest_myDefaultCaps.contextStereo = Draw::Atoi (theArgVec[1]) != 0;
Handle(Graphic3d_Camera) aCamera;
Graphic3d_RenderingParams* aParams = NULL;
Graphic3d_StereoMode aMode = Graphic3d_StereoMode_QuadBuffer;
if (!aView.IsNull())
{
aParams = &aView->ChangeRenderingParams();
aMode = aParams->StereoMode;
aCamera = aView->Camera();
}
ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
{
Standard_CString anArg = theArgVec[anArgIter];
TCollection_AsciiString aFlag (anArg);
aFlag.LowerCase();
if (anUpdateTool.parseRedrawMode (aFlag))
{
continue;
}
else if (aFlag == "0"
|| aFlag == "off")
{
if (++anArgIter < theArgNb)
{
std::cout << "Error: wrong number of arguments!\n";
return 1;
}
if (!aCamera.IsNull()
&& aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
{
aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
}
ViewerTest_myDefaultCaps.contextStereo = Standard_False;
return 0;
}
else if (aFlag == "1"
|| aFlag == "on")
{
if (++anArgIter < theArgNb)
{
std::cout << "Error: wrong number of arguments!\n";
return 1;
}
if (!aCamera.IsNull())
{
aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
}
ViewerTest_myDefaultCaps.contextStereo = Standard_True;
return 0;
}
else if (aFlag == "-reverse"
|| aFlag == "-reversed"
|| aFlag == "-swap")
{
Standard_Boolean toEnable = Standard_True;
if (++anArgIter < theArgNb
&& !parseOnOff (theArgVec[anArgIter], toEnable))
{
--anArgIter;
}
aParams->ToReverseStereo = toEnable;
}
else if (aFlag == "-noreverse"
|| aFlag == "-noswap")
{
Standard_Boolean toDisable = Standard_True;
if (++anArgIter < theArgNb
&& !parseOnOff (theArgVec[anArgIter], toDisable))
{
--anArgIter;
}
aParams->ToReverseStereo = !toDisable;
}
else if (aFlag == "-mode"
|| aFlag == "-stereomode")
{
if (++anArgIter >= theArgNb
|| !parseStereoMode (theArgVec[anArgIter], aMode))
{
std::cout << "Error: syntax error at '" << anArg << "'\n";
return 1;
}
if (aMode == Graphic3d_StereoMode_QuadBuffer)
{
ViewerTest_myDefaultCaps.contextStereo = Standard_True;
}
}
else if (aFlag == "-anaglyph"
|| aFlag == "-anaglyphfilter")
{
Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
if (++anArgIter >= theArgNb
|| !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
{
std::cout << "Error: syntax error at '" << anArg << "'\n";
return 1;
}
aMode = Graphic3d_StereoMode_Anaglyph;
aParams->AnaglyphFilter = aFilter;
}
else if (parseStereoMode (anArg, aMode)) // short syntax
{
if (aMode == Graphic3d_StereoMode_QuadBuffer)
{
ViewerTest_myDefaultCaps.contextStereo = Standard_True;
}
}
else
{
std::cout << "Error: syntax error at '" << anArg << "'\n";
return 1;
}
}
if (!aView.IsNull())
{
aParams->StereoMode = aMode;
aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
}
return 0;
}
@ -8761,11 +9061,27 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
__FILE__, VVbo, group);
theCommands.Add ("vstereo",
"\nvstereo [{0|1}] : turn stereo usage On/Off; affects only newly displayed objects",
"vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
"\n\t\t: [-anaglyph Filter]"
"\n\t\t: Control stereo output mode. Available modes for -mode:"
"\n\t\t: quadBuffer - OpenGL QuadBuffer stereo,"
"\n\t\t: requires driver support."
"\n\t\t: Should be called BEFORE vinit!"
"\n\t\t: anaglyph - Anaglyph glasses"
"\n\t\t: rowInterlaced - row-interlaced display"
"\n\t\t: columnInterlaced - column-interlaced display"
"\n\t\t: chessBoard - chess-board output"
"\n\t\t: sideBySide - horizontal pair"
"\n\t\t: overUnder - vertical pair"
"\n\t\t: Available Anaglyph filters for -anaglyph:"
"\n\t\t: redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
"\n\t\t: greenMagentaSimple",
__FILE__, VStereo, group);
theCommands.Add ("vcaps",
"vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
"\n\t\t: [-compatibleContext {0|1}]"
"\n\t\t: [-vsync {0|1}]"
"\n\t\t: [-quadBuffer {0|1}] [-stereo {0|1}]"
"\n\t\t: [-softMode {0|1}] [-noupdate|-update]"
"\n\t\t: Modify particular graphic driver options:"
"\n\t\t: FFP - use fixed-function pipeline instead of"
@ -8774,9 +9090,11 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: VBO - use Vertex Buffer Object (copy vertex"
"\n\t\t: arrays to GPU memory)"
"\n\t\t: sprite - use textured sprites instead of bitmaps"
"\n\t\t: vsync - switch VSync on or off"
"\n\t\t: Context creation options:"
"\n\t\t: softMode - software OpenGL implementation"
"\n\t\t: compatibleProfile - backward-compatible profile"
"\n\t\t: quadbuffer - QuadBuffer"
"\n\t\t: Unlike vrenderparams, these parameters control alternative"
"\n\t\t: rendering paths producing the same visual result when"
"\n\t\t: possible."

View File

@ -109,10 +109,13 @@ void Visual3d_View::SetWindow (const Handle(Aspect_Window)& theWindow)
MyCView.DefWindow.XWindow = theWindow->NativeHandle();
MyCView.DefWindow.XParentWindow = theWindow->NativeParentHandle();
Standard_Integer Width, Height;
theWindow->Size (Width, Height);
MyCView.DefWindow.dx = Width;
MyCView.DefWindow.dy = Height;
Standard_Integer aWidth = 0, aHeight = 0, aLeft = 0, aTop = 0;
theWindow->Position (aLeft, aTop, aWidth, aHeight);
theWindow->Size (aWidth, aHeight);
MyCView.DefWindow.left = aLeft;
MyCView.DefWindow.top = aTop;
MyCView.DefWindow.dx = aWidth;
MyCView.DefWindow.dy = aHeight;
Standard_Real R, G, B;
MyBackground = MyWindow->Background ();
@ -270,7 +273,11 @@ void Visual3d_View::SetRatio()
const Aspect_TypeOfUpdate anUpdateMode = myViewManager->UpdateMode();
myViewManager->SetUpdateMode (Aspect_TOU_WAIT);
Standard_Integer aWidth, aHeight;
Standard_Integer aWidth = 0, aHeight = 0, aLeft = 0, aTop = 0;
MyWindow->Position (aLeft, aTop, aWidth, aHeight);
MyCView.DefWindow.left = aLeft;
MyCView.DefWindow.top = aTop;
MyWindow->Size (aWidth, aHeight);
if (aWidth > 0 && aHeight > 0)
{

View File

@ -16,8 +16,8 @@ vinit
vsetdispmode 1
vdisplay b
vfit
vdump ${imagedir}/texture_409.png rgb 409 409
vdump ${imagedir}/texture_412.png rgb 412 412
vdump ${imagedir}/texture_409.png -buffer rgb -width 409 -height 409
vdump ${imagedir}/texture_412.png -buffer rgb -width 412 -height 412
# texture loaded correctly
vtexture b ${imagedir}/texture_412.png

View File

@ -15,16 +15,16 @@ vcamera -fov 45 -iodType relative -iod 0.05 -zfocustype relative -zfocus 1.0
vcamera -ortho
vfit
set aTitle "ortho"
vdump $imagedir/${casename}_${aTitle}.png rgb 512 512
vdump $imagedir/${casename}_${aTitle}.png -buffer rgb -width 512 -height 512
vcamera -persp
vfit
set aTitle "persp"
vdump $imagedir/${casename}_${aTitle}.png rgb 512 512
vdump $imagedir/${casename}_${aTitle}.png -buffer rgb -width 512 -height 512
vcamera -stereo
set aTitle "stereoR"
vdump $imagedir/${casename}_${aTitle}.png rgb 512 512 R
vdump $imagedir/${casename}_${aTitle}.png -buffer rgb -width 512 -height 512 -stereo R
set aTitle "stereoL"
vdump $imagedir/${casename}_${aTitle}.png rgb 512 512 L
vdump $imagedir/${casename}_${aTitle}.png -buffer rgb -width 512 -height 512 -stereo L
# test context stereo mode swicthing
# if not supported by hardware it must not crash
@ -35,4 +35,4 @@ vdisplay b
vcamera -stereo
vfit
set aTitle "afterSwitch"
vdump $imagedir/${casename}_${aTitle}.png rgb 512 512 R
vdump $imagedir/${casename}_${aTitle}.png -buffer rgb -width 512 -height 512 -stereo R

33
tests/v3d/glsl/stereo Normal file
View File

@ -0,0 +1,33 @@
puts "========"
puts "Stereo output modes"
puts "========"
restore [locate_data_file occ/fuse.brep] f
vinit View1
vclear
vsetdispmode 1
vaxo
vdisplay f
vfit
vrotate -0.5 0.0 0.0
vstereo -mode anaglyph
vfit
vdump $::imagedir/${::casename}_anaglyph.png -stereo blend
vstereo -mode columnInterlaced
vdump $::imagedir/${::casename}_col.png -stereo blend
vstereo -mode chessBoard
vdump $::imagedir/${::casename}_chess.png -stereo blend
vstereo -mode rowInterlaced
vdump $::imagedir/${::casename}_row.png -stereo blend
vstereo -mode sideBySide
vdump $::imagedir/${::casename}_sbs_anamorph.png -stereo blend
vstereo -mode overUnder
vdump $::imagedir/${::casename}_overunder_anamorph.png -stereo blend
vdump $::imagedir/${::casename}_sbs.png -stereo sbs