mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-08 13:30:04 +00:00
Added Metal support
This commit is contained in:
parent
023a2b8649
commit
30cd2df37c
1
.gitignore
vendored
Normal file → Executable file
1
.gitignore
vendored
Normal file → Executable file
@ -6,3 +6,4 @@
|
||||
*.pyc
|
||||
osdshim_wrap.cpp
|
||||
shim.py
|
||||
.DS_Store
|
||||
|
@ -74,6 +74,10 @@ if (NOT DEFINED CMAKE_LIBDIR_BASE)
|
||||
set( CMAKE_LIBDIR_BASE lib )
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_FRAMEWORKDIR_BASE)
|
||||
set( CMAKE_FRAMEWORKDIR_BASE Frameworks )
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_PLUGINDIR_BASE)
|
||||
set( CMAKE_PLUGINDIR_BASE plugin )
|
||||
endif()
|
||||
@ -140,6 +144,11 @@ endif()
|
||||
# which point to directories outside the build tree to the install RPATH
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
# ensure that ARC is shown as enabled in the Xcode UI
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")
|
||||
endif()
|
||||
|
||||
|
||||
set(OSD_COMPILER_FLAGS)
|
||||
|
||||
@ -293,6 +302,7 @@ option(NO_CUDA "Disable CUDA backend" OFF)
|
||||
option(NO_OPENCL "Disable OpenCL backend" OFF)
|
||||
option(NO_CLEW "Disable CLEW wrapper library" OFF)
|
||||
option(NO_OPENGL "Disable OpenGL support")
|
||||
option(NO_METAL "Disable Metal support" OFF)
|
||||
option(NO_DX "Disable DirectX support")
|
||||
option(NO_TESTS "Disable all tests")
|
||||
option(NO_GLTESTS "Disable GL tests")
|
||||
@ -332,6 +342,9 @@ if(NOT NO_PTEX)
|
||||
find_package(PTex 2.0)
|
||||
find_package(ZLIB 1.2)
|
||||
endif()
|
||||
if(APPLE AND NOT NO_METAL)
|
||||
find_package(Metal)
|
||||
endif()
|
||||
if (OPENGL_FOUND AND NOT IOS)
|
||||
add_definitions(
|
||||
-DOPENSUBDIV_HAS_OPENGL
|
||||
@ -390,6 +403,10 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( METAL_FOUND AND NOT NO_METAL)
|
||||
set(OSD_GPU TRUE)
|
||||
endif()
|
||||
|
||||
if( OPENGL_FOUND AND NOT NO_OPENGL)
|
||||
set(OSD_GPU TRUE)
|
||||
endif()
|
||||
@ -657,6 +674,11 @@ macro(_add_executable target folder)
|
||||
if(CMAKE_COMPILER_IS_ICC)
|
||||
target_link_libraries(${target} ${ICC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_property (TARGET ${target} APPEND_STRING PROPERTY
|
||||
COMPILE_FLAGS " -fobjc-arc ")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
@ -674,6 +696,11 @@ macro(_add_possibly_cuda_executable target folder)
|
||||
if(CMAKE_COMPILER_IS_ICC)
|
||||
target_link_libraries(${target} ${ICC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_property (TARGET ${target} APPEND_STRING PROPERTY
|
||||
COMPILE_FLAGS " -fobjc-arc ")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
@ -686,6 +713,11 @@ macro(_add_possibly_cuda_library target folder)
|
||||
add_library(${target} ${ARGN})
|
||||
endif()
|
||||
set_target_properties(${target} PROPERTIES FOLDER ${folder})
|
||||
|
||||
if(APPLE)
|
||||
set_property (TARGET ${target} APPEND_STRING PROPERTY
|
||||
COMPILE_FLAGS " -fobjc-arc ")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
@ -716,6 +748,11 @@ macro(_add_glfw_executable target folder)
|
||||
# endforeach()
|
||||
# endif()
|
||||
|
||||
if(APPLE)
|
||||
set_property (TARGET ${target} APPEND_STRING PROPERTY
|
||||
COMPILE_FLAGS " -fobjc-arc ")
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -738,7 +775,7 @@ endif()
|
||||
|
||||
add_subdirectory(opensubdiv)
|
||||
|
||||
if (NOT ANDROID AND NOT IOS) # XXXdyu
|
||||
if (NOT ANDROID) # XXXdyu
|
||||
add_subdirectory(regression)
|
||||
endif()
|
||||
|
||||
|
26
README.md
26
README.md
@ -8,8 +8,8 @@ Feel free to use it and let us know what you think.
|
||||
|
||||
For more details about OpenSubdiv, see [Pixar Graphics Technologies](http://graphics.pixar.com).
|
||||
|
||||
| | Linux | Windows |
|
||||
|:------:|:-------:|:---------:|
|
||||
| | Linux | Windows | macOS | iOS |
|
||||
|:------:|:-------:|:---------:|:------:|:---:|
|
||||
| master | [![Linux Build Status](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv.svg?branch=master)](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mcmwg4q9m8kgi9im/branch/master?svg=true)](https://ci.appveyor.com/project/c64kernal/opensubdiv-ddr8q) |
|
||||
| dev | [![Linux Build Status](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv.svg?branch=dev)](https://travis-ci.org/PixarAnimationStudios/OpenSubdiv) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mcmwg4q9m8kgi9im/branch/dev?svg=true)](https://ci.appveyor.com/project/c64kernal/opensubdiv-ddr8q) |
|
||||
|
||||
@ -40,6 +40,7 @@ For more details about OpenSubdiv, see [Pixar Graphics Technologies](http://grap
|
||||
| TBB <br> https://www.threadingbuildingblocks.org | 4.0 | TBB backend |
|
||||
| OpenCL <br> http://www.khronos.org/opencl | 1.1 | CL backend |
|
||||
| DX11 SDK <br> http://www.microsoft.com/download/details.aspx?id=6812| | DX backend |
|
||||
| Metal <br> https://developer.apple.com/metal/ | 1.2 | Metal backend |
|
||||
|
||||
* Examples/Documents optional requirements:
|
||||
|
||||
@ -102,16 +103,30 @@ cmake -D NO_PTEX=1 -D NO_DOC=1 \
|
||||
make
|
||||
```
|
||||
|
||||
### OSX
|
||||
### macOS
|
||||
|
||||
```
|
||||
cmake -D NO_PTEX=1 -D NO_DOC=1 \
|
||||
cmake -G Xcode -D NO_PTEX=1 -D NO_DOC=1 \
|
||||
-D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 \
|
||||
-D GLFW_LOCATION="*YOUR GLFW INSTALL LOCATION*" \
|
||||
..
|
||||
make
|
||||
```
|
||||
|
||||
### iOS
|
||||
|
||||
* Because OpenSubdiv uses a self-built build tool (stringify) as part of the build process, you'll want to build for macOS and build the stringify target
|
||||
|
||||
```
|
||||
SDKROOT=$(xcrun --sdk iphoneos --show-sdk-path) cmake -D NO_PTEX=1 -D NO_DOC=1 \
|
||||
-D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 \
|
||||
-D STRINGIFY_LOCATION="*YOUR MACOS BUILD LOCATION*"/bin/stringify \
|
||||
-D CMAKE_TOOLCHAIN_FILE=../cmake/iOSToolchain.cmake -G Xcode \
|
||||
..
|
||||
```
|
||||
|
||||
* This will produce an "OpenSubdiv.xcodeproj" that can be open and the targets 'mtlViewer' and 'mtlPtexViewer' (if NO_PTEX is ommitted and libPtex.a is installed in the iOS SDK) that can be run
|
||||
|
||||
### Useful cmake options and environment variables
|
||||
|
||||
````
|
||||
@ -119,11 +134,13 @@ make
|
||||
|
||||
-DCMAKE_INSTALL_PREFIX=[base path to install OpenSubdiv]
|
||||
-DCMAKE_LIBDIR_BASE=[library directory basename (default: lib)]
|
||||
-DCMAKE_TOOLCHAIN_FILE=[toolchain file for crossplatform builds]
|
||||
|
||||
-DCUDA_TOOLKIT_ROOT_DIR=[path to CUDA Toolkit]
|
||||
-DPTEX_LOCATION=[path to Ptex]
|
||||
-DGLEW_LOCATION=[path to GLEW]
|
||||
-DGLFW_LOCATION=[path to GLFW]
|
||||
-DSTRINGIFY_LOCATION=[path to stringify utility]
|
||||
|
||||
-DNO_LIB=1 // disable the opensubdiv libs build (caveat emptor)
|
||||
-DNO_EXAMPLES=1 // disable examples build
|
||||
@ -137,5 +154,6 @@ make
|
||||
-DNO_OPENCL=1 // disable OpenCL
|
||||
-DNO_OPENGL=1 // disable OpenGL
|
||||
-DNO_CLEW=1 // disable CLEW wrapper library
|
||||
-DNO_METAL=1 // disable Metal
|
||||
````
|
||||
|
||||
|
22
cmake/FindMetal.cmake
Normal file
22
cmake/FindMetal.cmake
Normal file
@ -0,0 +1,22 @@
|
||||
if(APPLE)
|
||||
find_path( METAL_INCLUDE_DIR
|
||||
Metal/Metal.h
|
||||
)
|
||||
|
||||
find_library( METAL_FRAMEWORKS Metal )
|
||||
|
||||
if(METAL_FRAMEWORKS)
|
||||
set( METAL_LIBRARIES "-framework Metal -framework Foundation" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
set( METAL_FOUND "NO" )
|
||||
if(METAL_LIBRARIES)
|
||||
set( METAL_FOUND "YES" )
|
||||
endif(METAL_LIBRARIES)
|
||||
|
||||
mark_as_advanced(
|
||||
METAL_INCLUDE_DIR
|
||||
METAL_LIBRARIES
|
||||
)
|
@ -63,13 +63,24 @@ elseif (APPLE)
|
||||
"$ENV{PTEX_LOCATION}/include"
|
||||
PATHS
|
||||
DOC "The directory where Ptexture.h resides")
|
||||
find_library( PTEX_LIBRARY
|
||||
NAMES
|
||||
Ptex libPtex.a
|
||||
PATHS
|
||||
"${PTEX_LOCATION}/lib"
|
||||
"$ENV{PTEX_LOCATION}/lib"
|
||||
DOC "The Ptex Library")
|
||||
if (IOS)
|
||||
#IOS needs to link with the static version of ptex
|
||||
find_library( PTEX_LIBRARY
|
||||
NAMES
|
||||
libPtex.a
|
||||
PATHS
|
||||
"${PTEX_LOCATION}/lib"
|
||||
"$ENV{PTEX_LOCATION}/lib"
|
||||
DOC "The Ptex Library")
|
||||
else ()
|
||||
find_library( PTEX_LIBRARY
|
||||
NAMES
|
||||
Ptex libPtex.a
|
||||
PATHS
|
||||
"${PTEX_LOCATION}/lib"
|
||||
"$ENV{PTEX_LOCATION}/lib"
|
||||
DOC "The Ptex Library")
|
||||
endif()
|
||||
else ()
|
||||
find_path( PTEX_INCLUDE_DIR
|
||||
NAMES
|
||||
|
50
cmake/iOSToolchain.cmake
Normal file
50
cmake/iOSToolchain.cmake
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
|
||||
set(SDKROOT $ENV{SDKROOT})
|
||||
set(RC_ARCHS $ENV{RC_ARCHS})
|
||||
separate_arguments(RC_ARCHS)
|
||||
set(ARCH_FLAGS "-arch arm64")
|
||||
foreach(ARCH ${RC_ARCHS})
|
||||
set(ARCH_FLAGS "${ARCH_FLAGS} -arch ${ARCH}")
|
||||
endforeach(ARCH)
|
||||
|
||||
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} PlatformPath OUTPUT_VARIABLE DEVROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} ProductVersion OUTPUT_VARIABLE SDKVER OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND xcodebuild -version -sdk ${SDKROOT} Path OUTPUT_VARIABLE SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND xcrun -sdk ${SDKROOT} -f cc OUTPUT_VARIABLE CC OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND xcrun -sdk ${SDKROOT} -f c++ OUTPUT_VARIABLE CXX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Darwin)
|
||||
set(CMAKE_SYSTEM_VERSION 9)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
set (iPhone 1)
|
||||
set (iPhoneOS 1)
|
||||
set (iPhoneOS_VERSION ${SDKVER})
|
||||
set (IOS 1)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH "${SDKROOT}" "${DEVROOT}")
|
||||
set(CMAKE_OSX_SYSROOT "${SDKROOT}")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
set(CMAKE_MACOSX_BUNDLE YES)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
|
||||
|
||||
string(FIND ${DEVROOT} ".platform" PLATFORM_END REVERSE)
|
||||
string(FIND ${DEVROOT} "/" PLATFORM_START REVERSE)
|
||||
math(EXPR PLATFORM_START "${PLATFORM_START} + 1")
|
||||
math(EXPR PLATFORM_LENGTH "${PLATFORM_END} - ${PLATFORM_START}")
|
||||
string(SUBSTRING ${DEVROOT} ${PLATFORM_START} ${PLATFORM_LENGTH} PLATFORM)
|
||||
string(TOLOWER ${PLATFORM} PLATFORM)
|
||||
set(VERSIONMIN "-m${PLATFORM}-version-min=${SDKVER}")
|
||||
|
||||
set(DEPLOYMENT_TARGET "${SDKVER}")
|
||||
|
||||
set(CMAKE_C_COMPILER "${CC}")
|
||||
set(CMAKE_CXX_COMPILER "${CXX}")
|
||||
set(CMAKE_CROSSCOMPILING 1)
|
||||
set(CMAKE_C_FLAGS "${ARCH_FLAGS} ${VERSIONMIN} -isysroot ${SDKROOT}" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_FLAGS "${ARCH_FLAGS} ${VERSIONMIN} -isysroot ${SDKROOT}" CACHE STRING "" FORCE)
|
@ -79,3 +79,9 @@ if (DXSDK_FOUND AND NOT NO_DX)
|
||||
|
||||
endif()
|
||||
|
||||
if (METAL_FOUND AND NOT NO_METAL)
|
||||
add_subdirectory(mtlViewer)
|
||||
if(PTEX_FOUND)
|
||||
add_subdirectory(mtlPtexViewer)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -25,6 +25,7 @@
|
||||
set(EXAMPLES_COMMON_SHADER_FILES
|
||||
glslPtexCommon.glsl
|
||||
hlslPtexCommon.hlsl
|
||||
mtlPtexCommon.metal
|
||||
)
|
||||
|
||||
set(EXAMPLES_COMMON_SOURCE_FILES
|
||||
@ -120,6 +121,21 @@ if(CUDA_FOUND)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(METAL_FOUND)
|
||||
include_directories("${METAL_INCLUDE_DIR}")
|
||||
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
|
||||
mtlControlMeshDisplay.mm
|
||||
mtlUtils.mm
|
||||
mtlHud.mm
|
||||
)
|
||||
list(APPEND EXAMPLES_COMMON_HEADER_FILES
|
||||
mtlControlMeshDisplay.h
|
||||
mtlUtils.h
|
||||
mtlHud.h
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
if( PTEX_FOUND )
|
||||
list(APPEND EXAMPLES_COMMON_HEADER_FILES
|
||||
@ -144,6 +160,14 @@ if( PTEX_FOUND )
|
||||
d3d11PtexMipmapTexture.h
|
||||
)
|
||||
endif()
|
||||
if( METAL_FOUND )
|
||||
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
|
||||
mtlPtexMipmapTexture.mm
|
||||
)
|
||||
list(APPEND EXAMPLES_COMMON_HEADER_FILES
|
||||
mtlPtexMipmapTexture.h
|
||||
)
|
||||
endif()
|
||||
include_directories( "${PTEX_INCLUDE_DIR}" )
|
||||
list(APPEND PLATFORM_CPU_LIBRARIES
|
||||
${PTEX_LIBRARY}
|
||||
@ -158,7 +182,7 @@ include_directories(
|
||||
|
||||
set(INC_FILES )
|
||||
|
||||
if(OPENGL_FOUND OR DXSDK_FOUND)
|
||||
if(OPENGL_FOUND OR DXSDK_FOUND OR METAL_FOUND)
|
||||
_stringify("${EXAMPLES_COMMON_SHADER_FILES}" INC_FILES)
|
||||
|
||||
source_group("Shaders" FILES ${EXAMPLES_COMMON_SHADER_FILES})
|
||||
|
@ -31,15 +31,28 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define OSD_HUD_USE_FUNCTION_POINTERS (__cplusplus <= 199711L)
|
||||
|
||||
#if !OSD_HUD_USE_FUNCTION_POINTERS
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
#include "hud.h"
|
||||
|
||||
class Hud
|
||||
{
|
||||
public:
|
||||
#if OSD_HUD_USE_FUNCTION_POINTERS
|
||||
typedef void (*RadioButtonCallback)(int c);
|
||||
typedef void (*CheckBoxCallback)(bool checked, int data);
|
||||
typedef void (*SliderCallback)(float value, int data);
|
||||
typedef void (*PullDownCallback)(int value);
|
||||
#else
|
||||
typedef std::function<void(int)> RadioButtonCallback;
|
||||
typedef std::function<void(bool,int)> CheckBoxCallback;
|
||||
typedef std::function<void(float, int)> SliderCallback;
|
||||
typedef std::function<void(int)> PullDownCallback;
|
||||
#endif
|
||||
|
||||
Hud();
|
||||
virtual ~Hud();
|
||||
|
62
examples/common/mtlControlMeshDisplay.h
Normal file
62
examples/common/mtlControlMeshDisplay.h
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H
|
||||
#define OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
#include <far/topologyLevel.h>
|
||||
|
||||
class MTLControlMeshDisplay {
|
||||
public:
|
||||
MTLControlMeshDisplay(id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor);
|
||||
~MTLControlMeshDisplay() = default;
|
||||
|
||||
void Draw(id<MTLRenderCommandEncoder> encoder,
|
||||
id<MTLBuffer> vertexBuffer,
|
||||
const float *modelViewProjectionMatrix);
|
||||
|
||||
void SetTopology(OpenSubdiv::Far::TopologyLevel const &level);
|
||||
|
||||
bool GetEdgesDisplay() const { return _displayEdges; }
|
||||
void SetEdgesDisplay(bool display) { _displayEdges = display; }
|
||||
bool GetVerticesDisplay() const { return _displayVertices; }
|
||||
void SetVerticesDisplay(bool display) { _displayVertices = display; }
|
||||
|
||||
private:
|
||||
bool createProgram(MTLRenderPipelineDescriptor* pipelineDescriptor);
|
||||
|
||||
bool _displayEdges;
|
||||
bool _displayVertices;
|
||||
|
||||
id<MTLDevice> _device;
|
||||
|
||||
int _numEdges, _numPoints;
|
||||
id<MTLRenderPipelineState> _renderPipelineState;
|
||||
id<MTLBuffer> _vertexSharpnessBuffer;
|
||||
id<MTLBuffer> _edgeSharpnessBuffer;
|
||||
id<MTLBuffer> _edgeIndicesBuffer;
|
||||
};
|
||||
|
||||
#endif // OPENSUBDIV_EXAMPLES_MTL_CONTROL_MESH_DISPLAY_H
|
167
examples/common/mtlControlMeshDisplay.mm
Normal file
167
examples/common/mtlControlMeshDisplay.mm
Normal file
@ -0,0 +1,167 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "mtlControlMeshDisplay.h"
|
||||
#include <cassert>
|
||||
#include "mtlUtils.h"
|
||||
|
||||
static const char* s_Shader = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
float4 sharpnessToColor(float s) {
|
||||
// 0.0 2.0 4.0
|
||||
// green --- yellow --- red
|
||||
return float4(min(1.0, s * 0.5),
|
||||
min(1.0, 2.0 - s * 0.5),
|
||||
0.0, 1.0);
|
||||
}
|
||||
|
||||
struct DrawData
|
||||
{
|
||||
float4x4 ModelViewProjectionMatrix;
|
||||
};
|
||||
|
||||
struct VertexData
|
||||
{
|
||||
float3 position [[attribute(0)]];
|
||||
float sharpness [[attribute(1)]];
|
||||
};
|
||||
|
||||
struct FragmentData
|
||||
{
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
};
|
||||
|
||||
vertex FragmentData vs_main(VertexData in [[stage_in]],
|
||||
const constant DrawData& drawData [[buffer(2)]]
|
||||
)
|
||||
{
|
||||
FragmentData out;
|
||||
out.position = drawData.ModelViewProjectionMatrix * float4(in.position, 1.0);
|
||||
out.color = sharpnessToColor(in.sharpness);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fs_main(FragmentData in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
||||
)";
|
||||
|
||||
MTLControlMeshDisplay::MTLControlMeshDisplay(id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor)
|
||||
: _device(device), _displayEdges(false), _displayVertices(false), _numEdges(0), _numPoints(0) {
|
||||
const auto result = createProgram(pipelineDescriptor);
|
||||
assert(result && "Failed to create program for MTLControlMeshDisplay");
|
||||
}
|
||||
|
||||
void MTLControlMeshDisplay::SetTopology(OpenSubdiv::Far::TopologyLevel const &level) {
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
_numEdges = level.GetNumEdges();
|
||||
_numPoints = level.GetNumVertices();
|
||||
|
||||
std::vector<int> edgeIndices;
|
||||
std::vector<float> edgeSharpness;
|
||||
std::vector<float> vertSharpness;
|
||||
|
||||
edgeIndices.reserve(_numEdges * 2);
|
||||
edgeSharpness.reserve(_numEdges);
|
||||
vertSharpness.reserve(_numPoints);
|
||||
|
||||
for(int i = 0; i < _numEdges; i++) {
|
||||
const auto verts = level.GetEdgeVertices(i);
|
||||
edgeIndices.emplace_back(verts[0]);
|
||||
edgeIndices.emplace_back(verts[1]);
|
||||
edgeSharpness.emplace_back(level.GetEdgeSharpness(i));
|
||||
}
|
||||
|
||||
for(int i = 0; i < _numPoints; i++) {
|
||||
vertSharpness.emplace_back(level.GetVertexSharpness(i));
|
||||
}
|
||||
|
||||
_edgeIndicesBuffer = Osd::MTLNewBufferFromVector(_device, edgeIndices);
|
||||
_edgeSharpnessBuffer = Osd::MTLNewBufferFromVector(_device, edgeSharpness);
|
||||
_vertexSharpnessBuffer = Osd::MTLNewBufferFromVector(_device, vertSharpness);
|
||||
}
|
||||
|
||||
bool MTLControlMeshDisplay::createProgram(MTLRenderPipelineDescriptor* _pipelineDescriptor) {
|
||||
const auto options = [MTLCompileOptions new];
|
||||
NSError* error = nil;
|
||||
|
||||
const auto library = [_device newLibraryWithSource:@(s_Shader) options:options error:&error];
|
||||
if(!library) {
|
||||
printf("Failed to create library for MTLControlMeshDisplay\n%s\n", error ? [[error localizedDescription] UTF8String] : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto vertexFunction = [library newFunctionWithName:@"vs_main"];
|
||||
const auto fragmentFunction = [library newFunctionWithName:@"fs_main"];
|
||||
|
||||
MTLRenderPipelineDescriptor* pipelineDescriptor = [_pipelineDescriptor copy];
|
||||
pipelineDescriptor.vertexFunction = vertexFunction;
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction;
|
||||
const auto vertexDescriptor = pipelineDescriptor.vertexDescriptor;
|
||||
vertexDescriptor.layouts[1].stride = sizeof(float) * 6;
|
||||
vertexDescriptor.layouts[1].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
vertexDescriptor.layouts[1].stepRate = 1;
|
||||
vertexDescriptor.attributes[1].bufferIndex = 1;
|
||||
vertexDescriptor.attributes[1].offset = 0;
|
||||
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat3;
|
||||
|
||||
_renderPipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
|
||||
|
||||
if(!_renderPipelineState) {
|
||||
printf("Failed to create render pipeline state for MTLControlMeshDisplay\n%s\n", error ? [[error localizedDescription] UTF8String] : "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MTLControlMeshDisplay::Draw(id<MTLRenderCommandEncoder> encoder,
|
||||
id<MTLBuffer> vertexBuffer,
|
||||
const float *modelViewProjectionMatrix) {
|
||||
[encoder setRenderPipelineState: _renderPipelineState];
|
||||
[encoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
|
||||
[encoder setVertexBytes:modelViewProjectionMatrix length: sizeof(float) * 16 atIndex:2];
|
||||
|
||||
if(_displayEdges) {
|
||||
[encoder setVertexBuffer:_edgeSharpnessBuffer offset:0 atIndex:1];
|
||||
[encoder drawIndexedPrimitives:MTLPrimitiveTypeLine
|
||||
indexCount:_numEdges * 2
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:_edgeIndicesBuffer
|
||||
indexBufferOffset:0
|
||||
instanceCount:1
|
||||
baseVertex:0
|
||||
baseInstance:0];
|
||||
}
|
||||
|
||||
if(_displayVertices) {
|
||||
[encoder setVertexBuffer:_vertexSharpnessBuffer offset:0 atIndex:1];
|
||||
[encoder drawPrimitives:MTLPrimitiveTypePoint
|
||||
vertexStart:0
|
||||
vertexCount:_numPoints];
|
||||
}
|
||||
}
|
72
examples/common/mtlHud.h
Normal file
72
examples/common/mtlHud.h
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// Copyright 2016 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_EXAMPLES_MTL_HUD_H
|
||||
#define OPENSUBDIV_EXAMPLES_MTL_HUD_H
|
||||
|
||||
@protocol MTLTexture;
|
||||
@protocol MTLBuffer;
|
||||
@protocol MTLRenderCommandEncoder;
|
||||
@protocol MTLRenderPipelineState;
|
||||
@protocol MTLDevice;
|
||||
@class MTLRenderPipelineDescriptor;
|
||||
@class MTLDepthStencilDescriptor;
|
||||
|
||||
#include "hud.h"
|
||||
#include "mtlUtils.h"
|
||||
|
||||
class MTLhud : public Hud {
|
||||
|
||||
public:
|
||||
MTLhud();
|
||||
~MTLhud();
|
||||
|
||||
virtual void Init(id<MTLDevice> device, MTLRenderPipelineDescriptor* parentPipelineDescriptor, MTLDepthStencilDescriptor* depthStencilStateDescriptor,
|
||||
int width, int height, int framebufferWidth, int framebufferHeight);
|
||||
|
||||
virtual void Rebuild(int width, int height,
|
||||
int framebufferWidth, int framebufferHeight);
|
||||
|
||||
virtual bool Flush(id<MTLRenderCommandEncoder> encoder);
|
||||
|
||||
id<MTLTexture> GetFontTexture() const {
|
||||
return _fontTexture;
|
||||
}
|
||||
|
||||
void FillBackground(id<MTLRenderCommandEncoder> encoder);
|
||||
|
||||
float UIScale = 1.0f;
|
||||
|
||||
private:
|
||||
id<MTLDevice> _device;
|
||||
id<MTLTexture> _fontTexture;
|
||||
OpenSubdiv::OPENSUBDIV_VERSION::Osd::MTLRingBuffer<float, 1> _staticBuffer;
|
||||
OpenSubdiv::OPENSUBDIV_VERSION::Osd::MTLRingBuffer<float, 3> _dynamicBuffer;
|
||||
|
||||
id<MTLRenderPipelineState> _fgPipelineState, _bgPipelineState;
|
||||
id<MTLDepthStencilState> _depthStencilState;
|
||||
};
|
||||
|
||||
|
||||
#endif //OPENSUBDIV_EXAMPLES_MTL_HUD_H
|
208
examples/common/mtlHud.mm
Normal file
208
examples/common/mtlHud.mm
Normal file
@ -0,0 +1,208 @@
|
||||
//
|
||||
// Copyright 2016 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "mtlHud.h"
|
||||
#include "font_image.h"
|
||||
#include "simple_math.h"
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
static const char* shaderSource = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct VertexInput {
|
||||
float2 position [[attribute(0)]];
|
||||
float3 color [[attribute(1)]];
|
||||
float2 uv [[attribute(2)]];
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
float2 uv;
|
||||
};
|
||||
|
||||
|
||||
|
||||
vertex VertexOutput fg_vertex(
|
||||
VertexInput in [[stage_in]],
|
||||
constant const float4x4& ModelViewProjectionMatrix [[buffer(1)]],
|
||||
constant const float& UIScale [[buffer(2)]]
|
||||
) {
|
||||
VertexOutput out;
|
||||
|
||||
out.position = ModelViewProjectionMatrix * float4(in.position * UIScale, 0, 1);
|
||||
out.color = float4(in.color, 1);
|
||||
out.uv = in.uv;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 fg_fragment(
|
||||
VertexOutput in [[stage_in]],
|
||||
texture2d<float, access::sample> fontTexture [[texture(0)]]
|
||||
) {
|
||||
|
||||
constexpr sampler s = sampler(coord::normalized, address::clamp_to_zero, filter::nearest);
|
||||
auto c = fontTexture.sample(s, in.uv);
|
||||
if(c.a == 0)
|
||||
discard_fragment();
|
||||
|
||||
return c * in.color;
|
||||
}
|
||||
|
||||
constant float4 bgVertices[] = {
|
||||
{-1, 1, 0, 1},
|
||||
{1, 1, 0, 1},
|
||||
{-1, -1, 0, 1},
|
||||
{1, -1, 0, 1}
|
||||
};
|
||||
|
||||
vertex VertexOutput bg_vertex(uint vertex_id [[vertex_id]]) {
|
||||
VertexOutput out;
|
||||
|
||||
out.position = bgVertices[vertex_id];
|
||||
out.uv = bgVertices[vertex_id].xy * 0.5 + 0.5 * 3.14159;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 bg_fragment(VertexOutput in [[stage_in]]) {
|
||||
return float4(float3(mix(0.1, 0.5, sin(in.uv.y))), 1);
|
||||
}
|
||||
|
||||
)";
|
||||
|
||||
|
||||
MTLhud::MTLhud() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
MTLhud::~MTLhud() {
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MTLhud::Init(id<MTLDevice> device, MTLRenderPipelineDescriptor* parentPipelineDescriptor, MTLDepthStencilDescriptor* depthStencilStateDescriptor, int width, int height, int framebufferWidth, int framebufferHeight) {
|
||||
Hud::Init(width, height, framebufferWidth, framebufferHeight);
|
||||
|
||||
@autoreleasepool {
|
||||
_device = device;
|
||||
const auto textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:FONT_TEXTURE_WIDTH height:FONT_TEXTURE_HEIGHT mipmapped:false];
|
||||
_fontTexture = [_device newTextureWithDescriptor:textureDescriptor];
|
||||
[_fontTexture replaceRegion: { {0, 0, 0}, {FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, 1} } mipmapLevel:0 withBytes:font_image bytesPerRow:4 * FONT_TEXTURE_WIDTH];
|
||||
|
||||
NSError* err = nil;
|
||||
const auto library = [_device newLibraryWithSource:@(shaderSource) options:nil error:&err];
|
||||
assert(err == nil);
|
||||
|
||||
const auto renderPipelineDescriptor = (MTLRenderPipelineDescriptor*)[parentPipelineDescriptor copy];
|
||||
renderPipelineDescriptor.vertexFunction = [library newFunctionWithName:@"bg_vertex"];
|
||||
renderPipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"bg_fragment"];
|
||||
|
||||
_bgPipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&err];
|
||||
|
||||
renderPipelineDescriptor.vertexFunction = [library newFunctionWithName:@"fg_vertex"];
|
||||
renderPipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"fg_fragment"];
|
||||
const auto vertexDescriptor = renderPipelineDescriptor.vertexDescriptor;
|
||||
|
||||
vertexDescriptor.layouts[0].stride = sizeof(float) * 7;
|
||||
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
vertexDescriptor.layouts[0].stepRate = 1;
|
||||
|
||||
vertexDescriptor.attributes[0].offset = 0;
|
||||
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2;
|
||||
vertexDescriptor.attributes[0].bufferIndex = 0;
|
||||
|
||||
vertexDescriptor.attributes[1].offset = sizeof(float) * 2;
|
||||
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat3;
|
||||
vertexDescriptor.attributes[1].bufferIndex = 0;
|
||||
|
||||
vertexDescriptor.attributes[2].offset = sizeof(float) * 5;
|
||||
vertexDescriptor.attributes[2].format = MTLVertexFormatFloat2;
|
||||
vertexDescriptor.attributes[2].bufferIndex = 0;
|
||||
|
||||
_fgPipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&err];
|
||||
|
||||
_depthStencilState = [_device newDepthStencilStateWithDescriptor:depthStencilStateDescriptor];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MTLhud::Rebuild(int width, int height, int framebufferWidth, int framebufferHeight) {
|
||||
Hud::Rebuild(width, height, framebufferWidth, framebufferHeight);
|
||||
|
||||
_staticBuffer.alloc(_device, getStaticVboSource().size(), @"MTLhud static buffer");
|
||||
std::copy(getStaticVboSource().begin(), getStaticVboSource().end(), _staticBuffer.data());
|
||||
_staticBuffer.markModified();
|
||||
}
|
||||
|
||||
bool
|
||||
MTLhud::Flush(id<MTLRenderCommandEncoder> encoder) {
|
||||
if(!Hud::Flush())
|
||||
return false;
|
||||
|
||||
if(_dynamicBuffer.buffer().length < sizeof(float) * getVboSource().size()) {
|
||||
_dynamicBuffer.alloc(_device, getVboSource().size(), @"MTLhud dynamic buffer");
|
||||
} else {
|
||||
_dynamicBuffer.next();
|
||||
}
|
||||
|
||||
std::copy(getVboSource().begin(), getVboSource().end(), _dynamicBuffer.data());
|
||||
_dynamicBuffer.markModified();
|
||||
const auto numVertices = getVboSource().size() / 7;
|
||||
getVboSource().clear();
|
||||
|
||||
float proj[16];
|
||||
ortho(proj, 0, 0, float(GetWidth()), float(GetHeight()));
|
||||
|
||||
[encoder setVertexBuffer: _dynamicBuffer.buffer() offset:0 atIndex:0];
|
||||
[encoder setRenderPipelineState: _fgPipelineState];
|
||||
[encoder setDepthStencilState: _depthStencilState];
|
||||
[encoder setVertexBytes: proj length: sizeof(proj) atIndex:1];
|
||||
[encoder setVertexBytes: &UIScale length:sizeof(UIScale) atIndex:2];
|
||||
[encoder setFragmentTexture: _fontTexture atIndex:0];
|
||||
|
||||
if(numVertices > 0) {
|
||||
[encoder setVertexBuffer:_dynamicBuffer.buffer() offset:0 atIndex:0];
|
||||
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: numVertices];
|
||||
}
|
||||
|
||||
auto numStaticVertices = [_staticBuffer.buffer() length] / (7 * sizeof(float));
|
||||
if(numStaticVertices > 0) {
|
||||
[encoder setVertexBuffer:_staticBuffer.buffer() offset:0 atIndex:0];
|
||||
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: numStaticVertices];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MTLhud::FillBackground(id<MTLRenderCommandEncoder> encoder) {
|
||||
[encoder setRenderPipelineState: _bgPipelineState];
|
||||
[encoder setDepthStencilState: _depthStencilState];
|
||||
[encoder drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: 4];
|
||||
}
|
383
examples/common/mtlPtexCommon.metal
Normal file
383
examples/common/mtlPtexCommon.metal
Normal file
@ -0,0 +1,383 @@
|
||||
#line 0 "examples/common/mtlPtexCommon.metal"
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Ptex.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
T lerp(T x, T y, float a)
|
||||
{
|
||||
return x + (y - x) * a;
|
||||
}
|
||||
|
||||
template<>
|
||||
int lerp<int>(int x, int y, float a)
|
||||
{
|
||||
return x + (y - x) * a;
|
||||
}
|
||||
|
||||
struct PtexPacking {
|
||||
int page;
|
||||
int nMipmap;
|
||||
int uOffset;
|
||||
int vOffset;
|
||||
int adjSizeDiffs[4];
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
PtexPacking getPtexPacking(device ushort* packings, int faceID)
|
||||
{
|
||||
PtexPacking packing;
|
||||
packing.page = packings[faceID*6+0];
|
||||
packing.nMipmap = packings[faceID*6+1];
|
||||
packing.uOffset = packings[faceID*6+2];
|
||||
packing.vOffset = packings[faceID*6+3];
|
||||
int wh = packings[faceID*6+5];
|
||||
packing.width = 1 << (wh >> 8);
|
||||
packing.height = 1 << (wh & 0xff);
|
||||
|
||||
int adjSizeDiffs = packings[faceID*6+4];
|
||||
packing.adjSizeDiffs[0] = (adjSizeDiffs >> 12) & 0xf;
|
||||
packing.adjSizeDiffs[1] = (adjSizeDiffs >> 8) & 0xf;
|
||||
packing.adjSizeDiffs[2] = (adjSizeDiffs >> 4) & 0xf;
|
||||
packing.adjSizeDiffs[3] = (adjSizeDiffs >> 0) & 0xf;
|
||||
|
||||
return packing;
|
||||
}
|
||||
|
||||
int computeMipmapOffsetU(int w, int level)
|
||||
{
|
||||
int width = 1 << w;
|
||||
int m = (0x55555555 & (width | (width-1))) << (w&1);
|
||||
int x = ~((1 << (w -((level-1)&~1))) - 1);
|
||||
return (m & x) + ((level+1)&~1);
|
||||
}
|
||||
|
||||
int computeMipmapOffsetV(int h, int level)
|
||||
{
|
||||
int height = 1 << h;
|
||||
int m = (0x55555555 & (height-1)) << ((h+1)&1);;
|
||||
int x = ~((1 << (h - (level&~1))) - 1 );
|
||||
return (m & x) + (level&~1);
|
||||
}
|
||||
|
||||
PtexPacking getPtexPacking(device ushort* packings, int faceID, int level)
|
||||
{
|
||||
PtexPacking packing;
|
||||
packing.page = packings[faceID*6+0];
|
||||
packing.nMipmap = packings[faceID*6+1];
|
||||
packing.uOffset = packings[faceID*6+2];
|
||||
packing.vOffset = packings[faceID*6+3];
|
||||
//int sizeDiffs = packings[faceID*6+4];
|
||||
int wh = packings[faceID*6+5];
|
||||
int w = wh >> 8;
|
||||
int h = wh & 0xff;
|
||||
|
||||
// clamp max level
|
||||
level = min(level, packing.nMipmap);
|
||||
|
||||
packing.uOffset += computeMipmapOffsetU(w, level);
|
||||
packing.vOffset += computeMipmapOffsetV(h, level);
|
||||
packing.width = 1 << (w-level);
|
||||
packing.height = 1 << (h-level);
|
||||
|
||||
return packing;
|
||||
}
|
||||
|
||||
void evalQuadraticBSpline(float u, thread float3& B, thread float3& BU)
|
||||
{
|
||||
B[0] = 0.5 * (u*u - 2.0*u + 1);
|
||||
B[1] = 0.5 + u - u*u;
|
||||
B[2] = 0.5 * u*u;
|
||||
|
||||
BU[0] = u - 1.0;
|
||||
BU[1] = 1 - 2 * u;
|
||||
BU[2] = u;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Non-Mipmap Lookups
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookupNearest(float4 patchCoord,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.read(uint2(), int()))
|
||||
{
|
||||
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID);
|
||||
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
|
||||
uv.y * ppack.height + ppack.vOffset);
|
||||
return float4(data.read(uint2(coords.x, coords.y), ppack.page));
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookupNearest(float4 patchCoord,
|
||||
int level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.read(uint2(), int()))
|
||||
{
|
||||
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID, level);
|
||||
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
|
||||
uv.y * ppack.height + ppack.vOffset);
|
||||
return float4(data.read(uint2(coords.x, coords.y), ppack.page));
|
||||
}
|
||||
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookupFast(float4 patchCoord,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.sample(sampler(), float2(), int()))
|
||||
{
|
||||
constexpr sampler smp(coord::normalized, address::clamp_to_edge, filter::linear);
|
||||
|
||||
float2 uv = clamp(patchCoord.xy, float2(0), float2(1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID);
|
||||
float2 coords = float2((uv.x * ppack.width + ppack.uOffset),
|
||||
(uv.y * ppack.height + ppack.vOffset)) / float2(data.get_width(), data.get_height());
|
||||
return data.sample(smp, coords, ppack.page);
|
||||
}
|
||||
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookupFast(float4 patchCoord,
|
||||
float level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.sample(sampler(), float2(), int(), bias(level)))
|
||||
{
|
||||
constexpr sampler smp(coord::normalized, address::clamp_to_edge, filter::linear);
|
||||
|
||||
float2 uv = clamp(patchCoord.xy, float2(0), float2(1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID, level);
|
||||
float2 coords = float2((uv.x * ppack.width + ppack.uOffset),
|
||||
(uv.y * ppack.height + ppack.vOffset)) / float2(data.get_width(), data.get_height());
|
||||
|
||||
return data.sample(smp, coords, ppack.page, bias(level));
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookup(float4 patchCoord,
|
||||
int level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.read(uint2(), int()))
|
||||
{
|
||||
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID, level);
|
||||
|
||||
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
|
||||
uv.y * ppack.height + ppack.vOffset);
|
||||
|
||||
coords -= float2(0.5, 0.5);
|
||||
|
||||
int c0X = int(floor(coords.x));
|
||||
int c1X = int(ceil(coords.x));
|
||||
int c0Y = int(floor(coords.y));
|
||||
int c1Y = int(ceil(coords.y));
|
||||
|
||||
float t = coords.x - float(c0X);
|
||||
float s = coords.y - float(c0Y);
|
||||
|
||||
const auto d0 = float4(data.read(uint2(c0X, c0Y), ppack.page));
|
||||
const auto d1 = float4(data.read(uint2(c0X, c1Y), ppack.page));
|
||||
const auto d2 = float4(data.read(uint2(c1X, c0Y), ppack.page));
|
||||
const auto d3 = float4(data.read(uint2(c1X, c1Y), ppack.page));
|
||||
|
||||
const auto result = (1.0f-t) * ((1.0f-s)*d0 + s*d1) + t * ((1.0f-s)*d2 + s*d3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexLookupQuadratic(thread float4& du,
|
||||
thread float4& dv,
|
||||
float4 patchCoord,
|
||||
int level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.read(uint2(), int()))
|
||||
{
|
||||
using dataType = decltype(data.read(uint2(), int()));
|
||||
|
||||
float2 uv = clamp(patchCoord.xy, float2(0,0), float2(1,1));
|
||||
int faceID = int(patchCoord.w);
|
||||
PtexPacking ppack = getPtexPacking(packings, faceID, level);
|
||||
|
||||
float2 coords = float2(uv.x * ppack.width + ppack.uOffset,
|
||||
uv.y * ppack.height + ppack.vOffset);
|
||||
|
||||
coords -= float2(0.5, 0.5);
|
||||
|
||||
int cX = int(round(coords.x));
|
||||
int cY = int(round(coords.y));
|
||||
|
||||
float x = 0.5 - (float(cX) - coords.x);
|
||||
float y = 0.5 - (float(cY) - coords.y);
|
||||
|
||||
dataType d[9];
|
||||
d[0] = data.read(uint2(cX-1, cY-1), ppack.page);
|
||||
d[1] = data.read(uint2(cX-1, cY-0), ppack.page);
|
||||
d[2] = data.read(uint2(cX-1, cY+1), ppack.page);
|
||||
d[3] = data.read(uint2(cX-0, cY-1), ppack.page);
|
||||
d[4] = data.read(uint2(cX-0, cY-0), ppack.page);
|
||||
d[5] = data.read(uint2(cX-0, cY+1), ppack.page);
|
||||
d[6] = data.read(uint2(cX+1, cY-1), ppack.page);
|
||||
d[7] = data.read(uint2(cX+1, cY-0), ppack.page);
|
||||
d[8] = data.read(uint2(cX+1, cY+1), ppack.page);
|
||||
|
||||
float3 B, D;
|
||||
dataType BUCP[3] = {dataType(0), dataType(0), dataType(0)},
|
||||
DUCP[3] = {dataType(0), dataType(0), dataType(0)};
|
||||
|
||||
evalQuadraticBSpline(y, B, D);
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
float4 A = d[i*3+j];
|
||||
BUCP[i] += A * B[j];
|
||||
DUCP[i] += A * D[j];
|
||||
}
|
||||
}
|
||||
|
||||
evalQuadraticBSpline(x, B, D);
|
||||
|
||||
dataType result = dataType(0);
|
||||
du = dataType(0);
|
||||
dv = dataType(0);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
result += B[i] * BUCP[i];
|
||||
du += D[i] * BUCP[i];
|
||||
dv += B[i] * DUCP[i];
|
||||
}
|
||||
|
||||
du *= ppack.width;
|
||||
dv *= ppack.height;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MipMap Lookups
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexMipmapLookupNearest(float4 patchCoord,
|
||||
float level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(PtexLookupNearest(patchCoord, int(), data, packings))
|
||||
{
|
||||
#if SEAMLESS_MIPMAP
|
||||
// diff level
|
||||
int faceID = int(patchCoord.w);
|
||||
float2 uv = patchCoord.xy;
|
||||
PtexPacking packing = getPtexPacking(packings, faceID);
|
||||
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
|
||||
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
|
||||
uv.y);
|
||||
#endif
|
||||
|
||||
int levelm = int(floor(level));
|
||||
int levelp = int(ceil(level));
|
||||
float t = level - float(levelm);
|
||||
|
||||
const auto result = (1-t) * PtexLookupNearest(patchCoord, levelm, data, packings)
|
||||
+ t * PtexLookupNearest(patchCoord, levelp, data, packings);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexMipmapLookup(float4 patchCoord,
|
||||
float level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(PtexLookup(patchCoord, int(), data, packings))
|
||||
{
|
||||
#if SEAMLESS_MIPMAP
|
||||
// diff level
|
||||
int faceID = int(patchCoord.w);
|
||||
float2 uv = patchCoord.xy;
|
||||
PtexPacking packing = getPtexPacking(packings, faceID);
|
||||
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
|
||||
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
|
||||
uv.y);
|
||||
#endif
|
||||
|
||||
int levelm = int(floor(level));
|
||||
int levelp = int(ceil(level));
|
||||
float t = level - float(levelm);
|
||||
|
||||
const auto result = (1-t) * PtexLookup(patchCoord, levelm, data, packings)
|
||||
+ t * PtexLookup(patchCoord, levelp, data, packings);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexMipmapLookupQuadratic(thread float4& du,
|
||||
thread float4& dv,
|
||||
float4 patchCoord,
|
||||
float level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(PtexLookupQuadratic(du, dv, patchCoord, int(), data, packings))
|
||||
{
|
||||
using dataType = decltype(PtexLookupQuadratic(du, dv, patchCoord, int(), data, packings));
|
||||
#if SEAMLESS_MIPMAP
|
||||
// diff level
|
||||
int faceID = int(patchCoord.w);
|
||||
float2 uv = patchCoord.xy;
|
||||
PtexPacking packing = getPtexPacking(packings, faceID);
|
||||
level += lerp(lerp(packing.adjSizeDiffs[0], packing.adjSizeDiffs[1], uv.x),
|
||||
lerp(packing.adjSizeDiffs[3], packing.adjSizeDiffs[2], uv.x),
|
||||
uv.y);
|
||||
#endif
|
||||
|
||||
int levelm = int(floor(level));
|
||||
int levelp = int(ceil(level));
|
||||
float t = level - float(levelm);
|
||||
|
||||
float4 du0, du1, dv0, dv1;
|
||||
const auto r0 = PtexLookupQuadratic(du0, dv0, patchCoord, levelm, data, packings);
|
||||
const auto r1 = PtexLookupQuadratic(du1, dv1, patchCoord, levelp, data, packings);
|
||||
|
||||
const auto result = lerp(r0, r1, t);
|
||||
du = lerp(du0, du1, t);
|
||||
dv = lerp(dv0, dv1, t);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Texture>
|
||||
auto PtexMipmapLookupQuadratic(float4 patchCoord,
|
||||
float level,
|
||||
Texture data,
|
||||
device ushort* packings) -> decltype(data.read(uint2(), int())) //decltype(PtexMipmapLookupQuadratic(float4(), float4(), patchCoord, level, packings)) //Not using the correct decltpye due to the need for thread& types
|
||||
{
|
||||
float4 du, dv;
|
||||
return PtexMipmapLookupQuadratic(du, dv, patchCoord, level, data, packings);
|
||||
}
|
58
examples/common/mtlPtexMipmapTexture.h
Normal file
58
examples/common/mtlPtexMipmapTexture.h
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_EXAMPLES_MTL_PTEX_MIPMAP_TEXTURE_H
|
||||
#define OPENSUBDIV_EXAMPLES_MTL_PTEX_MIPMAP_TEXTURE_H
|
||||
|
||||
#include <osd/mtlCommon.h>
|
||||
#include <osd/nonCopyable.h>
|
||||
#include <Ptexture.h>
|
||||
|
||||
|
||||
@protocol MTLBuffer;
|
||||
@protocol MTLTexture;
|
||||
@class MTLTextureDescriptor;
|
||||
|
||||
class MTLPtexMipmapTexture : OpenSubdiv::Osd::NonCopyable<MTLPtexMipmapTexture> {
|
||||
public:
|
||||
static MTLPtexMipmapTexture * Create(OpenSubdiv::Osd::MTLContext * deviceContext,
|
||||
PtexTexture * reader,
|
||||
int maxLevels = 10);
|
||||
|
||||
|
||||
static const char* GetShaderSource();
|
||||
|
||||
id<MTLBuffer> GetLayoutBuffer() const { return _layout; }
|
||||
id<MTLTexture> GetTexelsTexture() const { return _texels; }
|
||||
|
||||
private:
|
||||
MTLPtexMipmapTexture();
|
||||
|
||||
id<MTLBuffer> _layout;
|
||||
id<MTLTexture> _texels;
|
||||
|
||||
MTLTextureDescriptor* _textureDescriptor;
|
||||
};
|
||||
|
||||
#endif // OPENSUBDIV_EXAMPLES_MTL_PTEX_TEXTURE_H
|
121
examples/common/mtlPtexMipmapTexture.mm
Normal file
121
examples/common/mtlPtexMipmapTexture.mm
Normal file
@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "mtlPtexMipmapTexture.h"
|
||||
#include "ptexMipmapTextureLoader.h"
|
||||
#include <far/error.h>
|
||||
#include <Metal/Metal.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "mtlUtils.h"
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
MTLPtexMipmapTexture::MTLPtexMipmapTexture() :
|
||||
_layout(nil), _texels(nil), _textureDescriptor(nil) {
|
||||
}
|
||||
|
||||
const char* MTLPtexMipmapTexture::GetShaderSource() {
|
||||
static const char* shaderSource =
|
||||
#include "mtlPtexCommon.gen.h"
|
||||
;
|
||||
return shaderSource;
|
||||
}
|
||||
|
||||
MTLPtexMipmapTexture * MTLPtexMipmapTexture::Create(Osd::MTLContext *deviceContext, PtexTexture *reader, int maxLevels) {
|
||||
const auto maxNumPages = 2048;
|
||||
|
||||
PtexMipmapTextureLoader loader(reader, maxNumPages, maxLevels);
|
||||
const auto numFaces = loader.GetNumFaces();
|
||||
|
||||
const auto layoutBuffer = [deviceContext->device newBufferWithBytes:loader.GetLayoutBuffer() length:numFaces * 6 * sizeof(short) options:Osd::MTLDefaultStorageMode];
|
||||
|
||||
const auto textureDescriptor = [MTLTextureDescriptor new];
|
||||
int bpp = 0;
|
||||
textureDescriptor.pixelFormat = [&]() {
|
||||
const auto numChannels = reader->numChannels();
|
||||
switch(reader->dataType()) {
|
||||
case Ptex::dt_uint16:
|
||||
bpp = sizeof(short) * numChannels;
|
||||
switch(numChannels) {
|
||||
case 1: return MTLPixelFormatR16Unorm;
|
||||
case 2: return MTLPixelFormatRG16Unorm;
|
||||
case 3: assert("RGB16Uint not supported"); break;
|
||||
case 4: return MTLPixelFormatRGBA16Unorm;
|
||||
}
|
||||
case Ptex::dt_float:
|
||||
bpp = sizeof(float) * numChannels;
|
||||
switch(numChannels) {
|
||||
case 1: return MTLPixelFormatR32Float;
|
||||
case 2: return MTLPixelFormatRG32Float;
|
||||
case 3: assert("RGB32Float not supported"); break;
|
||||
case 4: return MTLPixelFormatRGBA32Float;
|
||||
}
|
||||
case Ptex::dt_half:
|
||||
bpp = sizeof(short) * numChannels;
|
||||
switch(numChannels) {
|
||||
case 1: return MTLPixelFormatR16Float;
|
||||
case 2: return MTLPixelFormatRG16Float;
|
||||
case 3: assert("RGB16Float not supported"); break;
|
||||
case 4: return MTLPixelFormatRGBA16Float;
|
||||
}
|
||||
default:
|
||||
bpp = numChannels;
|
||||
switch(numChannels) {
|
||||
case 1: return MTLPixelFormatR8Unorm;
|
||||
case 2: return MTLPixelFormatRG8Unorm;
|
||||
case 3: assert("RGB8Unorm not supported"); break;
|
||||
case 4: return MTLPixelFormatRGBA8Unorm;
|
||||
}
|
||||
}
|
||||
return MTLPixelFormatInvalid;
|
||||
}();
|
||||
textureDescriptor.width = loader.GetPageWidth();
|
||||
textureDescriptor.height = loader.GetPageHeight();
|
||||
textureDescriptor.arrayLength = loader.GetNumPages();
|
||||
textureDescriptor.mipmapLevelCount = 1;
|
||||
textureDescriptor.usage = MTLTextureUsageShaderRead;
|
||||
textureDescriptor.textureType = MTLTextureType2DArray;
|
||||
|
||||
const auto texelsTexture = [deviceContext->device newTextureWithDescriptor:textureDescriptor];
|
||||
if(!texelsTexture)
|
||||
return nullptr;
|
||||
|
||||
auto result = new MTLPtexMipmapTexture();
|
||||
result->_textureDescriptor = textureDescriptor;
|
||||
result->_layout = layoutBuffer;
|
||||
result->_texels = texelsTexture;
|
||||
|
||||
MTLRegion replaceRegion = MTLRegionMake2D(0, 0, loader.GetPageWidth(), loader.GetPageHeight());
|
||||
const auto bytesPerRow = loader.GetPageWidth() * bpp;
|
||||
const auto bytesPerImage = bytesPerRow * loader.GetPageHeight();
|
||||
for(auto i = 0; i < loader.GetNumPages(); i++) {
|
||||
[texelsTexture replaceRegion:replaceRegion mipmapLevel:0 slice:i
|
||||
withBytes:loader.GetTexelBuffer() + i * bytesPerImage bytesPerRow:bytesPerRow bytesPerImage:bytesPerImage];
|
||||
}
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
121
examples/common/mtlUtils.h
Normal file
121
examples/common/mtlUtils.h
Normal file
@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_EXAMPLES_MTL_UTILS_H
|
||||
#define OPENSUBDIV_EXAMPLES_MTL_UTILS_H
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
#include <cstring>
|
||||
#include <TargetConditionals.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Osd {
|
||||
#if TARGET_OS_EMBEDDED
|
||||
constexpr auto MTLDefaultStorageMode = MTLResourceStorageModeShared;
|
||||
#else
|
||||
constexpr auto MTLDefaultStorageMode = MTLResourceStorageModeManaged;
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
id<MTLBuffer> MTLNewBufferFromVector(id<MTLDevice> device, const std::vector<T>& vec) {
|
||||
const auto typeSize = sizeof(T);
|
||||
const auto bufferSize = typeSize * vec.size();
|
||||
return [device newBufferWithBytes:vec.data() length:bufferSize options:MTLDefaultStorageMode];
|
||||
}
|
||||
|
||||
template<typename DataType, size_t RingLength>
|
||||
class MTLRingBuffer {
|
||||
private:
|
||||
id<MTLBuffer> _buffers[RingLength];
|
||||
uint _bufferIndex;
|
||||
|
||||
public:
|
||||
template<typename SizedType = DataType>
|
||||
MTLRingBuffer(id<MTLDevice> device, size_t count, NSString* label, MTLResourceOptions options = MTLDefaultStorageMode) {
|
||||
alloc<SizedType>(device, count, options, label);
|
||||
}
|
||||
|
||||
MTLRingBuffer() {
|
||||
for(uint i = 0; i < RingLength; i++) {
|
||||
_buffers[i] = nil;
|
||||
}
|
||||
_bufferIndex = 0;
|
||||
}
|
||||
|
||||
void markModified() const {
|
||||
#if !TARGET_OS_EMBEDDED
|
||||
const auto bufferLength = [buffer() length];
|
||||
[buffer() didModifyRange: NSMakeRange(0, bufferLength)];
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename SizedType = DataType>
|
||||
void alloc(id<MTLDevice> device, size_t count, NSString* label, MTLResourceOptions options = MTLDefaultStorageMode) {
|
||||
if(count) {
|
||||
for(uint i = 0; i < RingLength; i++) {
|
||||
_buffers[i] = [device newBufferWithLength: count * sizeof(SizedType) options:options];
|
||||
_buffers[i].label = label;
|
||||
_bufferIndex = i;
|
||||
|
||||
if((options & MTLResourceStorageModePrivate) == 0)
|
||||
{
|
||||
memset(data(), 0, count * sizeof(SizedType));
|
||||
markModified();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(uint i = 0; i < RingLength; i++) {
|
||||
_buffers[i] = nil;
|
||||
}
|
||||
}
|
||||
_bufferIndex = 0;
|
||||
}
|
||||
|
||||
id<MTLBuffer> buffer() const {
|
||||
return _buffers[_bufferIndex];
|
||||
}
|
||||
|
||||
DataType* data() const {
|
||||
return reinterpret_cast<DataType*>([buffer() contents]);
|
||||
}
|
||||
|
||||
void next() {
|
||||
_bufferIndex = (_bufferIndex + 1) % RingLength;
|
||||
}
|
||||
|
||||
operator id<MTLBuffer>() const {
|
||||
return buffer();
|
||||
}
|
||||
|
||||
DataType* operator->() const {
|
||||
return data();
|
||||
}
|
||||
|
||||
DataType& operator[](int idx) const {
|
||||
return (data())[idx];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // OPENSUBDIV_EXAMPLES_MTL_UTILS_H
|
||||
} } using namespace OPENSUBDIV_VERSION; }
|
25
examples/common/mtlUtils.mm
Normal file
25
examples/common/mtlUtils.mm
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "mtlUtils.h"
|
119
examples/mtlPtexViewer/CMakeLists.txt
Normal file
119
examples/mtlPtexViewer/CMakeLists.txt
Normal file
@ -0,0 +1,119 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
# with the following modification; you may not use this file except in
|
||||
# compliance with the Apache License and the following modification to it:
|
||||
# Section 6. Trademarks. is deleted and replaced with:
|
||||
#
|
||||
# 6. Trademarks. This License does not grant permission to use the trade
|
||||
# names, trademarks, service marks, or product names of the Licensor
|
||||
# and its affiliates, except as required to comply with Section 4(c) of
|
||||
# the License and to reproduce the content of the NOTICE file.
|
||||
#
|
||||
# You may obtain a copy of the Apache License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the Apache License with the above modification is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the Apache License for the specific
|
||||
# language governing permissions and limitations under the Apache License.
|
||||
#
|
||||
|
||||
# *** mtlPtexViewer ***
|
||||
|
||||
if(IOS)
|
||||
set(BUNDLE_FILES
|
||||
"iOS/Base.lproj/LaunchScreen.storyboard"
|
||||
"iOS/Base.lproj/Main.storyboard"
|
||||
)
|
||||
set(PLATFORM_PLIST "iOS/Info.plist")
|
||||
set(PLATFORM_FILES
|
||||
"iOS/AppDelegate.h"
|
||||
"iOS/AppDelegate.m"
|
||||
"iOS/main.m"
|
||||
"iOS/ViewController.h"
|
||||
"iOS/ViewController.mm"
|
||||
)
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"-framework UIKit"
|
||||
"z"
|
||||
)
|
||||
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
else()
|
||||
set(BUNDLE_FILES
|
||||
"OSX/MainMenu.xib"
|
||||
)
|
||||
set(PLATFORM_PLIST "OSX/Info.plist")
|
||||
set(PLATFORM_FILES
|
||||
"OSX/AppDelegate.h"
|
||||
"OSX/AppDelegate.m"
|
||||
"OSX/main.m"
|
||||
"OSX/ViewController.h"
|
||||
"OSX/ViewController.mm"
|
||||
)
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"-framework OpenGL"
|
||||
"-framework AppKit"
|
||||
)
|
||||
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"${OPENSUBDIV_INCLUDE_DIR}"
|
||||
"${METAL_INCLUDE_DIR}"
|
||||
"${PTEX_INCLUDE_DIR}"
|
||||
)
|
||||
|
||||
list(APPEND PLATFORM_FILES
|
||||
"mtlPtexViewer.h"
|
||||
"mtlPtexViewer.mm"
|
||||
)
|
||||
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"osd_static_framework"
|
||||
"${METAL_LIBRARY}"
|
||||
"-framework MetalKit"
|
||||
"-framework Foundation"
|
||||
"-framework QuartzCore"
|
||||
"${PTEX_LIBRARY}"
|
||||
)
|
||||
|
||||
_stringify("mtlPtexViewer.metal" INC_FILES)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
_add_executable(mtlPtexViewer "examples/mtlPtexViewer"
|
||||
MACOSX_BUNDLE
|
||||
"${PLATFORM_FILES}"
|
||||
"${INC_FILES}"
|
||||
"${BUNDLE_FILES}"
|
||||
$<TARGET_OBJECTS:regression_common_obj>
|
||||
$<TARGET_OBJECTS:regression_far_utils_obj>
|
||||
$<TARGET_OBJECTS:examples_common_obj>
|
||||
)
|
||||
|
||||
|
||||
set_target_properties (mtlPtexViewer PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
RESOURCE "${BUNDLE_FILES}"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_LIST_DIR}/${PLATFORM_PLIST}"
|
||||
)
|
||||
|
||||
if(IOS)
|
||||
set_target_properties(mtlPtexViewer PROPERTIES
|
||||
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
set_property (TARGET mtlPtexViewer PROPERTY CXX_STANDARD 14)
|
||||
|
||||
target_link_libraries(mtlPtexViewer
|
||||
${PLATFORM_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
install(TARGETS mtlPtexViewer DESTINATION "${CMAKE_BINDIR_BASE}")
|
31
examples/mtlPtexViewer/OSX/AppDelegate.h
Normal file
31
examples/mtlPtexViewer/OSX/AppDelegate.h
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
|
||||
@end
|
||||
|
42
examples/mtlPtexViewer/OSX/AppDelegate.m
Normal file
42
examples/mtlPtexViewer/OSX/AppDelegate.m
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
@end
|
58
examples/mtlPtexViewer/OSX/AppIcon.appiconset/Contents.json
Normal file
58
examples/mtlPtexViewer/OSX/AppIcon.appiconset/Contents.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
34
examples/mtlPtexViewer/OSX/Info.plist
Normal file
34
examples/mtlPtexViewer/OSX/Info.plist
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2016 Apple. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
</dict>
|
||||
</plist>
|
686
examples/mtlPtexViewer/OSX/MainMenu.xib
Normal file
686
examples/mtlPtexViewer/OSX/MainMenu.xib
Normal file
@ -0,0 +1,686 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16C20" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="aZQ-9t-9YL" id="ke3-sq-jK1"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="aZQ-9t-9YL" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Test" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Test" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About NewApplication" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide NewApplication" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit NewApplication" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="KaW-ft-85H">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="jxT-CU-nIS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
||||
<items>
|
||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="Fal-I4-PZk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="J5U-5w-g23">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="YGs-j5-SAR">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="Lbh-J2-qVU">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="jFq-tB-4Kx">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="Nop-cj-93Q">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="BgM-ve-c93">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="RB4-Sm-HuC">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="NewApplication Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="1920" height="1080"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<view key="contentView" id="se5-gp-TjO" customClass="OSDView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<connections>
|
||||
<outlet property="menu" destination="AYu-sK-qS6" id="0eg-gK-PK4"/>
|
||||
</connections>
|
||||
</view>
|
||||
<point key="canvasLocation" x="172" y="11"/>
|
||||
</window>
|
||||
<viewController id="tdF-Vh-f4K" customClass="ViewController">
|
||||
<connections>
|
||||
<outlet property="view" destination="se5-gp-TjO" id="fc1-e3-wEk"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
</document>
|
66
examples/mtlPtexViewer/OSX/ViewController.h
Normal file
66
examples/mtlPtexViewer/OSX/ViewController.h
Normal file
@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "../mtlPtexViewer.h"
|
||||
#import "../../common/mtlHud.h"
|
||||
|
||||
@class ViewController;
|
||||
|
||||
@interface OSDView : MTKView {
|
||||
@public
|
||||
MTLhud hud;
|
||||
};
|
||||
|
||||
@property (nonatomic) ViewController* controller;
|
||||
@end
|
||||
|
||||
@interface ViewController : NSViewController<MTKViewDelegate, OSDRendererDelegate>
|
||||
@property (weak) IBOutlet OSDView *view;
|
||||
@property (nonatomic) OSDRenderer* osdRenderer;
|
||||
|
||||
- (IBAction)checkboxChanged:(NSButton *)sender;
|
||||
- (IBAction)popupChanged:(NSPopUpButton *)sender;
|
||||
- (IBAction)sliderChanged:(NSSlider *)sender;
|
||||
|
||||
@property (weak) IBOutlet NSTextField *frameTimeLabel;
|
||||
@property (weak) IBOutlet NSButton *wireframeCheckbox;
|
||||
@property (weak) IBOutlet NSButton *singleCreaseCheckbox;
|
||||
@property (weak) IBOutlet NSButton *patchIndexCheckbox;
|
||||
@property (weak) IBOutlet NSButton *patchClipCullingCheckbox;
|
||||
@property (weak) IBOutlet NSButton *backfaceCullingCheckbox;
|
||||
@property (weak) IBOutlet NSButton *backpatchCullingCheckbox;
|
||||
@property (weak) IBOutlet NSButton *screenspaceTessellationCheckbox;
|
||||
@property (weak) IBOutlet NSPopUpButton *modelPopup;
|
||||
@property (weak) IBOutlet NSPopUpButton *refinementLevelPopup;
|
||||
@property (weak) IBOutlet NSPopUpButton *tessellationLevelPopup;
|
||||
@property (weak) IBOutlet NSPopUpButton *displacementModePopup;
|
||||
@property (weak) IBOutlet NSPopUpButton *normalModePopup;
|
||||
@property (weak) IBOutlet NSPopUpButton *colorModePopup;
|
||||
@property (weak) IBOutlet NSSlider *displacementScaleSlider;
|
||||
@property (weak) IBOutlet NSSlider *mipmapBiasSlider;
|
||||
|
||||
|
||||
@end
|
461
examples/mtlPtexViewer/OSX/ViewController.mm
Normal file
461
examples/mtlPtexViewer/OSX/ViewController.mm
Normal file
@ -0,0 +1,461 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
|
||||
|
||||
enum {
|
||||
kHUD_RB_COLOR,
|
||||
kHUD_RB_SCHEME,
|
||||
kHUD_RB_LEVEL,
|
||||
kHUD_RB_DISPLACEMENT,
|
||||
kHUD_RB_NORMAL
|
||||
};
|
||||
|
||||
enum {
|
||||
kHUD_SL_MIPMAPBIAS,
|
||||
kHUD_SL_DISPLACEMENT,
|
||||
};
|
||||
|
||||
enum {
|
||||
kHUD_CB_DISPLAY_OCCLUSION,
|
||||
kHUD_CB_DISPLAY_SPECULAR,
|
||||
kHUD_CB_ANIMATE_VERTICES,
|
||||
kHUD_CB_VIEW_LOD,
|
||||
kHUD_CB_FRACTIONAL_SPACING,
|
||||
kHUD_CB_PATCH_CULL,
|
||||
kHUD_CB_FREEZE,
|
||||
kHUD_CB_ADAPTIVE,
|
||||
kHUD_CB_SEAMLESS_MIPMAP,
|
||||
};
|
||||
|
||||
@implementation OSDView {
|
||||
bool _mouseDown;
|
||||
NSPoint _lastMouse;
|
||||
}
|
||||
|
||||
-(void)mouseDown:(NSEvent *)event {
|
||||
if(event.buttonNumber == 0) {
|
||||
_lastMouse = [event locationInWindow];
|
||||
_mouseDown = !hud.MouseClick(_lastMouse.x, (self.bounds.size.height - _lastMouse.y));
|
||||
}
|
||||
[super mouseDown:event];
|
||||
}
|
||||
|
||||
-(void)mouseUp:(NSEvent *)event {
|
||||
if(event.buttonNumber == 0) {
|
||||
_mouseDown = false;
|
||||
_lastMouse = [event locationInWindow];
|
||||
hud.MouseRelease();
|
||||
}
|
||||
[super mouseUp:event];
|
||||
}
|
||||
|
||||
-(void)mouseDragged:(NSEvent *)event {
|
||||
auto mouse = [NSEvent mouseLocation];
|
||||
hud.MouseMotion(mouse.x, mouse.y);
|
||||
|
||||
if(_mouseDown) {
|
||||
CGPoint delta;
|
||||
delta.x = mouse.x - _lastMouse.x;
|
||||
delta.y = mouse.y - _lastMouse.y;
|
||||
_lastMouse = mouse;
|
||||
|
||||
_controller.osdRenderer.camera->rotationX += delta.x / 2.0;
|
||||
_controller.osdRenderer.camera->rotationY -= delta.y / 2.0;
|
||||
}
|
||||
[super mouseDragged:event];
|
||||
}
|
||||
|
||||
-(void)keyDown:(NSEvent *)event {
|
||||
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
|
||||
if(key == '=') {
|
||||
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16.0f);
|
||||
} else if (key == '-') {
|
||||
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0.0f);
|
||||
} else if(!hud.KeyDown(key))
|
||||
[super keyDown:event];
|
||||
}
|
||||
|
||||
-(void)scrollWheel:(NSEvent *)event {
|
||||
_controller.osdRenderer.camera->dollyDistance += event.deltaY / 100.0;
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder {
|
||||
return true;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
#define FRAME_HISTORY 30
|
||||
@implementation ViewController {
|
||||
id<MTLDevice> _device;
|
||||
id<MTLCommandQueue> _commandQueue;
|
||||
dispatch_semaphore_t _frameSemaphore;
|
||||
OSDRenderer* _osdRenderer;
|
||||
|
||||
unsigned _currentFrame;
|
||||
double _frameBeginTimestamp[FRAME_HISTORY];
|
||||
|
||||
NSMagnificationGestureRecognizer* _magnificationGesture;
|
||||
}
|
||||
|
||||
-(void)viewDidLoad {
|
||||
|
||||
_device = MTLCreateSystemDefaultDevice();
|
||||
_commandQueue = [_device newCommandQueue];
|
||||
|
||||
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
|
||||
|
||||
_frameSemaphore = dispatch_semaphore_create(3);
|
||||
|
||||
self.view.device = _device;
|
||||
self.view.delegate = self;
|
||||
self.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
|
||||
self.view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
|
||||
self.view.controller = self;
|
||||
self.view.sampleCount = 2;
|
||||
|
||||
|
||||
_osdRenderer.camera->aspectRatio = self.view.bounds.size.width / self.view.bounds.size.height;
|
||||
|
||||
_currentFrame = 0;
|
||||
|
||||
auto renderPipelineDescriptor = [MTLRenderPipelineDescriptor new];
|
||||
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
|
||||
renderPipelineDescriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
|
||||
renderPipelineDescriptor.sampleCount = self.view.sampleCount;
|
||||
|
||||
auto depthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
||||
depthStencilDescriptor.depthWriteEnabled = false;
|
||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||
|
||||
auto& hud = self.view->hud;
|
||||
hud.Init(_device, renderPipelineDescriptor, depthStencilDescriptor, self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
|
||||
|
||||
|
||||
auto callbackCheckbox = [=](bool checked, int ID) {
|
||||
switch(ID) {
|
||||
case kHUD_CB_FREEZE:
|
||||
self.osdRenderer.freeze = checked;
|
||||
break;
|
||||
case kHUD_CB_ADAPTIVE:
|
||||
self.osdRenderer.useAdaptive = checked;
|
||||
break;
|
||||
case kHUD_CB_VIEW_LOD:
|
||||
self.osdRenderer.useScreenspaceTessellation = checked;
|
||||
break;
|
||||
case kHUD_CB_PATCH_CULL:
|
||||
self.osdRenderer.usePatchClipCulling = checked;
|
||||
break;
|
||||
case kHUD_CB_ANIMATE_VERTICES:
|
||||
self.osdRenderer.animateVertices = checked;
|
||||
break;
|
||||
case kHUD_CB_DISPLAY_SPECULAR:
|
||||
self.osdRenderer.displaySpecular = checked;
|
||||
break;
|
||||
case kHUD_CB_DISPLAY_OCCLUSION:
|
||||
self.osdRenderer.displayOcclusion = checked;
|
||||
break;
|
||||
case kHUD_CB_FRACTIONAL_SPACING:
|
||||
self.osdRenderer.useFractionalTessellation = checked;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown checkbox ID" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackScheme = [=](int scheme) {
|
||||
return;
|
||||
};
|
||||
|
||||
auto callbackLevel = [=](int level) {
|
||||
self.osdRenderer.refinementLevel = level;
|
||||
};
|
||||
|
||||
auto callbackKernel = [=](int kernelType) {
|
||||
switch((KernelType)kernelType) {
|
||||
case kCPU:
|
||||
case kMetal:
|
||||
self.osdRenderer.kernelType = (KernelType)(kernelType);
|
||||
break;
|
||||
default:
|
||||
assert("Unknown kernelType" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackDisplayStyle = [=](int displayStyle) {
|
||||
switch((DisplayStyle)displayStyle) {
|
||||
case kDisplayStyleWire:
|
||||
case kDisplayStyleShaded:
|
||||
case kDisplayStyleWireOnShaded:
|
||||
self.osdRenderer.displayStyle = (DisplayStyle)displayStyle;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown displayStyle" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackColor = [=](int colorMode) {
|
||||
switch((ColorMode)colorMode) {
|
||||
case kColorModeNone:
|
||||
case kColorModeNormal:
|
||||
case kColorModePatchType:
|
||||
case kColorModePatchCoord:
|
||||
case kColorModePtexNearest:
|
||||
case kColorModePtexBilinear:
|
||||
case kColorModePtexHWBilinear:
|
||||
case kColorModePtexBiQuadratic:
|
||||
self.osdRenderer.colorMode = (ColorMode)colorMode;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown colorMode" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackDisplacement = [=](int displacementMode) {
|
||||
switch((DisplacementMode)displacementMode) {
|
||||
case kDisplacementModeNone:
|
||||
case kDisplacementModeBilinear:
|
||||
case kDisplacementModeHWBilinear:
|
||||
case kDisplacementModeBiQuadratic:
|
||||
self.osdRenderer.displacementMode = (DisplacementMode)displacementMode;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown displacementMode" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackNormal = [=](int normalMode) {
|
||||
switch((NormalMode)normalMode) {
|
||||
case kNormalModeBiQuadraticWG:
|
||||
case kNormalModeBiQuadratic:
|
||||
case kNormalModeScreenspace:
|
||||
case kNormalModeHWScreenspace:
|
||||
case kNormalModeSurface:
|
||||
self.osdRenderer.normalMode = (NormalMode)normalMode;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown normalMode" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackSlider = [=](float sliderValue, int sliderID) {
|
||||
switch(sliderID) {
|
||||
case kHUD_SL_DISPLACEMENT:
|
||||
self.osdRenderer.displacementScale = sliderValue;
|
||||
break;
|
||||
case kHUD_SL_MIPMAPBIAS:
|
||||
self.osdRenderer.mipmapBias = sliderValue;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown slider ID" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
if (_osdRenderer.ptexOcclusionFilename != NULL) {
|
||||
hud.AddCheckBox("Ambient Occlusion (A)", _osdRenderer.ptexOcclusionFilename,
|
||||
-200, 570, callbackCheckbox, kHUD_CB_DISPLAY_OCCLUSION, 'a');
|
||||
}
|
||||
if (_osdRenderer.ptexSpecularFilename != NULL)
|
||||
hud.AddCheckBox("Specular (S)", _osdRenderer.ptexSpecularFilename,
|
||||
-200, 590, callbackCheckbox, kHUD_CB_DISPLAY_SPECULAR, 's');
|
||||
|
||||
// if (_osdRenderer.ptexColorFilename || g_diffuseEnvironmentMap) {
|
||||
// hud.AddCheckBox("IBL (I)", g_ibl,
|
||||
// -200, 610, callbackCheckbox, HUD_CB_IBL, 'i');
|
||||
// }
|
||||
|
||||
hud.AddCheckBox("Animate vertices (M)", _osdRenderer.animateVertices,
|
||||
10, 30, callbackCheckbox, kHUD_CB_ANIMATE_VERTICES, 'm');
|
||||
hud.AddCheckBox("Screen space LOD (V)", _osdRenderer.useScreenspaceTessellation,
|
||||
10, 50, callbackCheckbox, kHUD_CB_VIEW_LOD, 'v');
|
||||
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
|
||||
10, 70, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
|
||||
hud.AddCheckBox("Frustum Patch Culling (B)", _osdRenderer.usePatchClipCulling,
|
||||
10, 90, callbackCheckbox, kHUD_CB_PATCH_CULL, 'b');
|
||||
hud.AddCheckBox("Freeze (spc)", _osdRenderer.freeze,
|
||||
10, 110, callbackCheckbox, kHUD_CB_FREEZE, ' ');
|
||||
// hud.AddCheckBox("Bloom (Y)", g_bloom,
|
||||
// 10, 130, callbackCheckbox, HUD_CB_BLOOM, 'y');
|
||||
|
||||
hud.AddRadioButton(kHUD_RB_SCHEME, "CATMARK", true, 10, 190, callbackScheme, 0);
|
||||
|
||||
// Ptex without Adaptive is not supported
|
||||
// hud.AddCheckBox("Adaptive (`)", _osdRenderer.useAdaptive,
|
||||
// 10, 300, callbackCheckbox, kHUD_CB_ADAPTIVE, '`');
|
||||
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
char level[16];
|
||||
sprintf(level, "Lv. %d", i);
|
||||
hud.AddRadioButton(kHUD_RB_LEVEL, level, _osdRenderer.refinementLevel == i,
|
||||
10, 320+i*20, callbackLevel, i, '0'+i);
|
||||
}
|
||||
|
||||
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
|
||||
hud.AddPullDownButton(compute_pulldown, "CPU", kCPU);
|
||||
hud.AddPullDownButton(compute_pulldown, "Metal", kMetal);
|
||||
|
||||
int shading_pulldown = hud.AddPullDown("Shading (W)", 250, 10, 250, callbackDisplayStyle, 'w');
|
||||
hud.AddPullDownButton(shading_pulldown, "Wire", kDisplayStyleWire, _osdRenderer.displayStyle == kDisplayStyleWire);
|
||||
hud.AddPullDownButton(shading_pulldown, "Shaded", kDisplayStyleShaded, _osdRenderer.displayStyle == kDisplayStyleShaded);
|
||||
hud.AddPullDownButton(shading_pulldown, "Wire+Shaded", kDisplayStyleWireOnShaded, _osdRenderer.displayStyle ==kDisplayStyleWireOnShaded);
|
||||
|
||||
hud.AddLabel("Color (C)", -200, 10);
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "None", (_osdRenderer.colorMode == kColorModeNone),
|
||||
-200, 30, callbackColor, kColorModeNone, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex Nearest", (_osdRenderer.colorMode == kColorModePtexNearest),
|
||||
-200, 50, callbackColor, kColorModePtexNearest, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex HW bilinear", (_osdRenderer.colorMode == kColorModePtexHWBilinear),
|
||||
-200, 70, callbackColor, kColorModePtexHWBilinear, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex bilinear", (_osdRenderer.colorMode == kColorModePtexBilinear),
|
||||
-200, 90, callbackColor, kColorModePtexBilinear, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Ptex biquadratic", (_osdRenderer.colorMode == kColorModePtexBiQuadratic),
|
||||
-200, 110, callbackColor, kColorModePtexBiQuadratic, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Patch type", (_osdRenderer.colorMode == kColorModePatchType),
|
||||
-200, 130, callbackColor, kColorModePatchType, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Patch coord", (_osdRenderer.colorMode == kColorModePatchCoord),
|
||||
-200, 150, callbackColor, kColorModePatchCoord, 'c');
|
||||
hud.AddRadioButton(kHUD_RB_COLOR, "Normal", (_osdRenderer.colorMode == kColorModeNormal),
|
||||
-200, 170, callbackColor, kColorModeNormal, 'c');
|
||||
|
||||
if (_osdRenderer.ptexDisplacementFilename) {
|
||||
hud.AddLabel("Displacement (D)", -200, 200);
|
||||
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "None",
|
||||
(_osdRenderer.displacementMode == kDisplacementModeNone),
|
||||
-200, 220, callbackDisplacement, kDisplacementModeNone, 'd');
|
||||
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "HW bilinear",
|
||||
(_osdRenderer.displacementMode == kDisplacementModeHWBilinear),
|
||||
-200, 240, callbackDisplacement, kDisplacementModeHWBilinear, 'd');
|
||||
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "Bilinear",
|
||||
(_osdRenderer.displacementMode == kDisplacementModeBilinear),
|
||||
-200, 260, callbackDisplacement, kDisplacementModeBilinear, 'd');
|
||||
hud.AddRadioButton(kHUD_RB_DISPLACEMENT, "Biquadratic",
|
||||
(_osdRenderer.displacementMode == kDisplacementModeBiQuadratic),
|
||||
-200, 280, callbackDisplacement, kDisplacementModeBiQuadratic, 'd');
|
||||
|
||||
{
|
||||
int y = 310;
|
||||
hud.AddLabel("Normal (N)", -200, y); y += 20;
|
||||
hud.AddRadioButton(kHUD_RB_NORMAL, "Surface",
|
||||
(_osdRenderer.normalMode == kNormalModeSurface),
|
||||
-200, y, callbackNormal, kNormalModeSurface, 'n'); y += 20;
|
||||
// hud.AddRadioButton(kHUD_RB_NORMAL, "Facet", //We can't really do NORMAL_FACET
|
||||
// (_osdRenderer.normalMode == NORMAL_FACET),
|
||||
// -200, y, callbackNormal, NORMAL_FACET, 'n'); y += 20;
|
||||
hud.AddRadioButton(kHUD_RB_NORMAL, "HW Screen space",
|
||||
(_osdRenderer.normalMode == kNormalModeHWScreenspace),
|
||||
-200, y, callbackNormal, kNormalModeHWScreenspace, 'n'); y += 20;
|
||||
hud.AddRadioButton(kHUD_RB_NORMAL, "Screen space",
|
||||
(_osdRenderer.normalMode == kNormalModeScreenspace),
|
||||
-200, y, callbackNormal, kNormalModeScreenspace, 'n'); y += 20;
|
||||
hud.AddRadioButton(kHUD_RB_NORMAL, "Biquadratic",
|
||||
(_osdRenderer.normalMode == kNormalModeBiQuadratic),
|
||||
-200, y, callbackNormal, kNormalModeBiQuadratic, 'n'); y += 20;
|
||||
hud.AddRadioButton(kHUD_RB_NORMAL, "Biquadratic WG",
|
||||
(_osdRenderer.normalMode == kNormalModeBiQuadraticWG),
|
||||
-200, y, callbackNormal, kNormalModeBiQuadraticWG, 'n'); y += 20;
|
||||
}
|
||||
}
|
||||
|
||||
hud.AddSlider("Mipmap Bias", 0, 5, 0,
|
||||
-200, 450, 20, false, callbackSlider, kHUD_SL_MIPMAPBIAS);
|
||||
hud.AddSlider("Displacement", 0, 5, 1,
|
||||
-200, 490, 20, false, callbackSlider, kHUD_SL_DISPLACEMENT);
|
||||
hud.AddCheckBox("Seamless Mipmap", _osdRenderer.useSeamlessMipmap,
|
||||
-200, 530, callbackCheckbox, kHUD_CB_SEAMLESS_MIPMAP, 'j');
|
||||
|
||||
hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
|
||||
}
|
||||
|
||||
-(void)drawInMTKView:(MTKView *)view {
|
||||
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
auto commandBuffer = [_commandQueue commandBuffer];
|
||||
|
||||
_osdRenderer.displacementScale = 3;
|
||||
|
||||
double avg = 0;
|
||||
for(int i = 0; i < FRAME_HISTORY; i++)
|
||||
avg += _frameBeginTimestamp[i];
|
||||
avg /= FRAME_HISTORY;
|
||||
|
||||
auto renderEncoder = [_osdRenderer drawFrame:commandBuffer];
|
||||
|
||||
auto& hud = self.view->hud;
|
||||
if(hud.IsVisible()) {
|
||||
hud.DrawString(10, -120, "Tess level : %f", _osdRenderer.tessellationLevel);
|
||||
hud.DrawString(10, -20, "FPS = %3.1f", 1.0 / avg);
|
||||
|
||||
//Disable Culling & Force Fill mode when drawing the UI
|
||||
[renderEncoder setTriangleFillMode:MTLTriangleFillModeFill];
|
||||
[renderEncoder setCullMode:MTLCullModeNone];
|
||||
self.view->hud.Flush(renderEncoder);
|
||||
};
|
||||
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
__weak auto blockSemaphore = _frameSemaphore;
|
||||
unsigned frameId = _currentFrame % FRAME_HISTORY;
|
||||
auto frameBeginTime = CACurrentMediaTime();
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
|
||||
dispatch_semaphore_signal(blockSemaphore);
|
||||
_frameBeginTimestamp[frameId] = CACurrentMediaTime() - frameBeginTime;
|
||||
}];
|
||||
|
||||
[commandBuffer presentDrawable:view.currentDrawable];
|
||||
[commandBuffer commit];
|
||||
|
||||
_currentFrame++;
|
||||
}
|
||||
|
||||
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
|
||||
_osdRenderer.camera->aspectRatio = size.width / size.height;
|
||||
}
|
||||
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
|
||||
}
|
||||
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
descriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
|
||||
descriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
|
||||
descriptor.sampleCount = self.view.sampleCount;
|
||||
}
|
||||
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
|
||||
return _commandQueue;
|
||||
}
|
||||
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
|
||||
return _device;
|
||||
}
|
||||
|
||||
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
|
||||
return self.view.currentRenderPassDescriptor;
|
||||
}
|
||||
@end
|
5
examples/mtlPtexViewer/OSX/main.m
Normal file
5
examples/mtlPtexViewer/OSX/main.m
Normal file
@ -0,0 +1,5 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
33
examples/mtlPtexViewer/iOS/AppDelegate.h
Normal file
33
examples/mtlPtexViewer/iOS/AppDelegate.h
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
61
examples/mtlPtexViewer/iOS/AppDelegate.m
Normal file
61
examples/mtlPtexViewer/iOS/AppDelegate.m
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,73 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1024" height="1366"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
265
examples/mtlPtexViewer/iOS/Base.lproj/Main.storyboard
Normal file
265
examples/mtlPtexViewer/iOS/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,265 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11173.2" systemVersion="16A264" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11143.2"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="MTKView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1366" height="1024"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Information Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ze8-2s-lED">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minimumValue="1" maximumValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="QQ6-5o-gla">
|
||||
<connections>
|
||||
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="uHZ-dB-XZV"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ref Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N12-GK-yLY">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="16" translatesAutoresizingMaskIntoConstraints="NO" id="eYp-5M-Rgk">
|
||||
<connections>
|
||||
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="mBg-38-OPM"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8kP-4Y-wzA">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="UsH-Nw-M31"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Wireframe" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FvR-NK-6s0" userLabel="Wireframe">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backpatch Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="esT-7h-XLG">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="P8z-O2-OLV">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="w7T-KH-L3E"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="5Ns-3P-r13">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ym1-Xw-wU6"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="fw1-9C-P6U">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="8kp-Rh-Yua"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backface Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw4-VH-Zwm">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Patch Clip Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5xP-bY-PgM">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Crease" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kuw-3r-nzl">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7yA-a6-Sq7">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="Yg5-z5-avS"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Screenspace Tessellation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ioY-T2-PEM">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tes Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlx-hC-oDg">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sDC-ZC-b6I">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ebT-0s-gYR"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lKi-xk-48C">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="229" id="Wpt-NP-71K"/>
|
||||
<constraint firstAttribute="height" constant="100" id="zRD-L8-taf"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="BYZ-38-t0r" id="9Fy-8F-lh4"/>
|
||||
<outlet property="delegate" destination="BYZ-38-t0r" id="AGI-ts-ucC"/>
|
||||
</connections>
|
||||
</pickerView>
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MhN-MJ-gcY">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="229" id="2un-1F-Mel"/>
|
||||
<constraint firstAttribute="height" constant="100" id="e85-YP-l4W"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="BYZ-38-t0r" id="fva-Gz-Lm9"/>
|
||||
<outlet property="delegate" destination="BYZ-38-t0r" id="vnc-OK-4c7"/>
|
||||
</connections>
|
||||
</pickerView>
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pci-qy-cH2">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="229" id="ZYQ-3j-No7"/>
|
||||
<constraint firstAttribute="height" constant="100" id="iBl-mj-oGZ"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="BYZ-38-t0r" id="e4g-y8-rgS"/>
|
||||
<outlet property="delegate" destination="BYZ-38-t0r" id="txx-qB-tmn"/>
|
||||
</connections>
|
||||
</pickerView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Color Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q2s-bO-zy8">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Normal Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="I4F-1D-Czt">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Displacement Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uci-PY-aOB">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="5Ee-cu-NZx">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="300" id="zHK-PA-cxQ"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<action selector="sliderChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="x6e-A1-PtP"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Mipmap Bias" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ep7-AF-66o">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Displacement" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2eJ-wE-QUZ">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="lg4-UF-DUA">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="300" id="SAY-uf-0VR"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<action selector="sliderChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="T6h-NW-Qz3"/>
|
||||
</connections>
|
||||
</slider>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="leading" secondItem="esT-7h-XLG" secondAttribute="trailing" constant="8" id="0zt-WU-LC3"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="404-z0-Fv7"/>
|
||||
<constraint firstItem="pci-qy-cH2" firstAttribute="centerY" secondItem="uci-PY-aOB" secondAttribute="centerY" id="51c-EC-nM4"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pci-qy-cH2" secondAttribute="trailing" constant="8" id="5JD-9Q-LoS"/>
|
||||
<constraint firstItem="MhN-MJ-gcY" firstAttribute="top" secondItem="pci-qy-cH2" secondAttribute="bottom" constant="8" id="5We-Fg-mqK"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="leading" secondItem="FvR-NK-6s0" secondAttribute="trailing" constant="8" id="5rd-n5-Uxl"/>
|
||||
<constraint firstItem="5Ee-cu-NZx" firstAttribute="trailing" secondItem="lg4-UF-DUA" secondAttribute="trailing" id="7wp-4z-St6"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="top" secondItem="7yA-a6-Sq7" secondAttribute="bottom" constant="8" id="81h-8V-det"/>
|
||||
<constraint firstItem="lKi-xk-48C" firstAttribute="leading" secondItem="Q2s-bO-zy8" secondAttribute="trailing" constant="8" id="9Hf-nv-kO7"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="leading" secondItem="dlx-hC-oDg" secondAttribute="trailing" constant="8" id="B0o-kO-368"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MhN-MJ-gcY" secondAttribute="trailing" constant="8" id="B5N-TG-DvY"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lKi-xk-48C" secondAttribute="trailing" constant="8" id="Dsf-kk-VQH"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="trailing" secondItem="7yA-a6-Sq7" secondAttribute="trailing" id="HIl-Xg-PwW"/>
|
||||
<constraint firstItem="ioY-T2-PEM" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="25" id="Kg5-1N-BpG"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="centerY" secondItem="esT-7h-XLG" secondAttribute="centerY" id="Oxf-2f-wTD"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="top" secondItem="QQ6-5o-gla" secondAttribute="bottom" constant="8" id="PJS-Lq-bIL"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="lKi-xk-48C" secondAttribute="bottom" constant="25" id="PnT-0o-uNH"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="top" secondItem="sDC-ZC-b6I" secondAttribute="bottom" constant="8" id="QC2-TN-FjW"/>
|
||||
<constraint firstItem="Ze8-2s-lED" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" id="SZK-UA-BiA"/>
|
||||
<constraint firstItem="MhN-MJ-gcY" firstAttribute="leading" secondItem="I4F-1D-Czt" secondAttribute="trailing" constant="8" id="T1r-ZQ-Jxi"/>
|
||||
<constraint firstItem="MhN-MJ-gcY" firstAttribute="centerY" secondItem="I4F-1D-Czt" secondAttribute="centerY" id="Tdj-kw-7IN"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="dlx-hC-oDg" secondAttribute="bottom" constant="25" id="U0T-iQ-NLt"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="fw1-9C-P6U" secondAttribute="bottom" constant="20" id="Uw7-fz-We7"/>
|
||||
<constraint firstItem="sDC-ZC-b6I" firstAttribute="leading" secondItem="kuw-3r-nzl" secondAttribute="trailing" constant="8" id="W06-wv-gqs"/>
|
||||
<constraint firstItem="QQ6-5o-gla" firstAttribute="centerY" secondItem="N12-GK-yLY" secondAttribute="centerY" id="bqu-uw-PqG"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="centerY" secondItem="dlx-hC-oDg" secondAttribute="centerY" id="cV6-GZ-8IP"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="leading" secondItem="ioY-T2-PEM" secondAttribute="trailing" constant="8" id="cqL-gl-vn2"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="5xP-bY-PgM" secondAttribute="bottom" constant="25" id="cqZ-ZJ-qwf"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="leading" secondItem="5xP-bY-PgM" secondAttribute="trailing" constant="8" id="dhX-z5-kgA"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="5Ee-cu-NZx" secondAttribute="bottom" constant="25" id="erc-MZ-6N2"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="centerY" secondItem="Iw4-VH-Zwm" secondAttribute="centerY" id="fEO-gM-cmZ"/>
|
||||
<constraint firstItem="lg4-UF-DUA" firstAttribute="leading" secondItem="2eJ-wE-QUZ" secondAttribute="trailing" constant="8" id="gne-Dp-lLU"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="gqA-q9-SK3"/>
|
||||
<constraint firstItem="lKi-xk-48C" firstAttribute="centerY" secondItem="Q2s-bO-zy8" secondAttribute="centerY" id="hdJ-mn-wba"/>
|
||||
<constraint firstItem="pci-qy-cH2" firstAttribute="leading" secondItem="uci-PY-aOB" secondAttribute="trailing" constant="8" id="huu-H0-Tby"/>
|
||||
<constraint firstItem="5Ee-cu-NZx" firstAttribute="centerY" secondItem="ep7-AF-66o" secondAttribute="centerY" id="iXa-Hm-SyL"/>
|
||||
<constraint firstItem="Ze8-2s-lED" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="20" id="kTX-YC-JKR"/>
|
||||
<constraint firstItem="dlx-hC-oDg" firstAttribute="leading" secondItem="fw1-9C-P6U" secondAttribute="trailing" constant="57" id="kk2-dV-2jk"/>
|
||||
<constraint firstItem="lKi-xk-48C" firstAttribute="top" secondItem="MhN-MJ-gcY" secondAttribute="bottom" constant="8" id="m49-1U-Jcw"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="centerY" secondItem="FvR-NK-6s0" secondAttribute="centerY" id="n3L-qM-7Pr"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="centerY" secondItem="5xP-bY-PgM" secondAttribute="centerY" id="nP1-Bt-GuV"/>
|
||||
<constraint firstItem="lKi-xk-48C" firstAttribute="top" secondItem="MhN-MJ-gcY" secondAttribute="bottom" constant="8" id="nrc-E0-3gd"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="trailing" secondItem="sDC-ZC-b6I" secondAttribute="trailing" id="pkW-Gf-A1P"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="top" secondItem="P8z-O2-OLV" secondAttribute="bottom" constant="8" id="pwK-2F-IIf"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="top" secondItem="8kP-4Y-wzA" secondAttribute="bottom" constant="8" id="q11-mD-QDz"/>
|
||||
<constraint firstItem="QQ6-5o-gla" firstAttribute="leading" secondItem="N12-GK-yLY" secondAttribute="trailing" constant="8" id="qBz-A8-IZc"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="rha-qA-vsj"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="ro3-hx-iLk"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="leading" secondItem="Iw4-VH-Zwm" secondAttribute="trailing" constant="8" id="ry7-bQ-bRa"/>
|
||||
<constraint firstItem="MhN-MJ-gcY" firstAttribute="top" secondItem="pci-qy-cH2" secondAttribute="bottom" constant="8" id="sR8-Lw-q9X"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="trailing" secondItem="QQ6-5o-gla" secondAttribute="trailing" id="syp-eW-H7w"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="tsW-3r-293"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="centerY" secondItem="ioY-T2-PEM" secondAttribute="centerY" id="wE0-Cg-4Qf"/>
|
||||
<constraint firstItem="sDC-ZC-b6I" firstAttribute="centerY" secondItem="kuw-3r-nzl" secondAttribute="centerY" id="wTg-7H-KXF"/>
|
||||
<constraint firstItem="lg4-UF-DUA" firstAttribute="centerY" secondItem="2eJ-wE-QUZ" secondAttribute="centerY" id="x0b-B2-XkG"/>
|
||||
<constraint firstItem="ep7-AF-66o" firstAttribute="leading" secondItem="eYp-5M-Rgk" secondAttribute="trailing" constant="52" id="xFx-Kb-IBp"/>
|
||||
<constraint firstItem="5Ee-cu-NZx" firstAttribute="leading" secondItem="ep7-AF-66o" secondAttribute="trailing" constant="8" id="xye-mn-VX2"/>
|
||||
<constraint firstItem="5Ee-cu-NZx" firstAttribute="top" secondItem="lg4-UF-DUA" secondAttribute="bottom" constant="8" id="zVK-yu-Uuz"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="backfaceCullingSwitch" destination="5Ns-3P-r13" id="n8X-2V-BRl"/>
|
||||
<outlet property="backpatchCullingSwitch" destination="P8z-O2-OLV" id="VIe-Lv-hsC"/>
|
||||
<outlet property="colorModePickerView" destination="lKi-xk-48C" id="u5F-aY-10I"/>
|
||||
<outlet property="displacementModePickerView" destination="pci-qy-cH2" id="jaV-1A-n0X"/>
|
||||
<outlet property="displacementSlider" destination="lg4-UF-DUA" id="BWG-lH-Qfm"/>
|
||||
<outlet property="frameTimeLabel" destination="Ze8-2s-lED" id="vLj-Id-oiv"/>
|
||||
<outlet property="mipmapBiasSlider" destination="5Ee-cu-NZx" id="WGF-bb-PaA"/>
|
||||
<outlet property="normalModePickerView" destination="MhN-MJ-gcY" id="LJw-CH-3Im"/>
|
||||
<outlet property="patchClipCullingSwitch" destination="fw1-9C-P6U" id="P2G-3F-eJh"/>
|
||||
<outlet property="refLvlLabel" destination="N12-GK-yLY" id="lXc-6r-pZY"/>
|
||||
<outlet property="refinementStepper" destination="QQ6-5o-gla" id="URK-fS-krY"/>
|
||||
<outlet property="screenspaceTessellationSwitch" destination="7yA-a6-Sq7" id="RpM-ER-4Oy"/>
|
||||
<outlet property="singleCreaseSwitch" destination="sDC-ZC-b6I" id="Arw-OY-Z4A"/>
|
||||
<outlet property="tesLvLlabel" destination="dlx-hC-oDg" id="haB-Hi-A9B"/>
|
||||
<outlet property="tessellationStepper" destination="eYp-5M-Rgk" id="IFG-H5-rJS"/>
|
||||
<outlet property="wireframeSwitch" destination="8kP-4Y-wzA" id="y3a-yu-4cs"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="463.83601756954607" y="406.640625"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<color key="tintColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
</document>
|
50
examples/mtlPtexViewer/iOS/Info.plist
Normal file
50
examples/mtlPtexViewer/iOS/Info.plist
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>mtlPtexViewer</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.osd.mtlPtexViewer</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>mtlPtexViewer</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>metal</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
57
examples/mtlPtexViewer/iOS/ViewController.h
Normal file
57
examples/mtlPtexViewer/iOS/ViewController.h
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "../mtlPtexViewer.h"
|
||||
|
||||
@interface ViewController : UIViewController<
|
||||
MTKViewDelegate,
|
||||
UIPickerViewDelegate,
|
||||
UIPickerViewDataSource,
|
||||
OSDRendererDelegate
|
||||
>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UILabel *refLvlLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *tesLvLlabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *frameTimeLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIPickerView *colorModePickerView;
|
||||
@property (weak, nonatomic) IBOutlet UIPickerView *normalModePickerView;
|
||||
@property (weak, nonatomic) IBOutlet UIPickerView *displacementModePickerView;
|
||||
@property (weak, nonatomic) IBOutlet UIStepper *tessellationStepper;
|
||||
@property (weak, nonatomic) IBOutlet UIStepper *refinementStepper;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *wireframeSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *backpatchCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *backfaceCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *patchClipCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *singleCreaseSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *screenspaceTessellationSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISlider *displacementSlider;
|
||||
@property (weak, nonatomic) IBOutlet UISlider *mipmapBiasSlider;
|
||||
- (IBAction)stepperChanged:(UIStepper *)sender;
|
||||
- (IBAction)switchChanged:(UISwitch *)sender;
|
||||
- (IBAction)sliderChanged:(UISlider*)sender;
|
||||
|
||||
@end
|
||||
|
297
examples/mtlPtexViewer/iOS/ViewController.mm
Normal file
297
examples/mtlPtexViewer/iOS/ViewController.mm
Normal file
@ -0,0 +1,297 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
|
||||
#define FRAME_HISTORY 30
|
||||
@interface ViewController ()
|
||||
{
|
||||
dispatch_semaphore_t _frameSemaphore;
|
||||
CGPoint _startTouch;
|
||||
bool _isTouching;
|
||||
OSDRenderer* _osdRenderer;
|
||||
MTKView* _view;
|
||||
id<MTLDevice> _device;
|
||||
id<MTLCommandQueue> _commandQueue;
|
||||
|
||||
double _frameTimes[FRAME_HISTORY];
|
||||
uint64_t _currentFrame;
|
||||
|
||||
UIPanGestureRecognizer *_zoomGesture;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
|
||||
_osdRenderer.camera->aspectRatio = size.width / size.height;
|
||||
}
|
||||
|
||||
-(void)drawInMTKView:(MTKView *)view {
|
||||
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
|
||||
auto commandBuffer = [_commandQueue commandBuffer];
|
||||
[_osdRenderer drawFrame:commandBuffer];
|
||||
|
||||
__weak auto blockSemaphore = _frameSemaphore;
|
||||
unsigned frameIndex = _currentFrame % FRAME_HISTORY;
|
||||
const auto beginTime = CACurrentMediaTime();
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
|
||||
dispatch_semaphore_signal(blockSemaphore);
|
||||
_frameTimes[frameIndex] = CACurrentMediaTime() - beginTime;
|
||||
}];
|
||||
[commandBuffer presentDrawable:_view.currentDrawable];
|
||||
[commandBuffer commit];
|
||||
_currentFrame++;
|
||||
|
||||
double frameAverage = 0;
|
||||
for(auto& x : _frameTimes)
|
||||
frameAverage += x;
|
||||
|
||||
frameAverage /= 30.0;
|
||||
|
||||
_frameTimeLabel.text = [NSString stringWithFormat:@"%0.2f ms", frameAverage * 1000.0];
|
||||
}
|
||||
|
||||
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||
return UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
_view = (MTKView*)self.view;
|
||||
_frameSemaphore = dispatch_semaphore_create(3);
|
||||
|
||||
_device = MTLCreateSystemDefaultDevice();
|
||||
_commandQueue = [_device newCommandQueue];
|
||||
|
||||
_view.device = _device;
|
||||
_view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
|
||||
_view.sampleCount = 2;
|
||||
_view.frame = CGRectMake(0, 0, 1920, 1080);
|
||||
_view.contentScaleFactor = 1;
|
||||
_view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
|
||||
|
||||
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
|
||||
|
||||
_view.delegate = self;
|
||||
|
||||
_zoomGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_zoomView)];
|
||||
_zoomGesture.minimumNumberOfTouches = 2;
|
||||
_zoomGesture.maximumNumberOfTouches = 2;
|
||||
_zoomGesture.cancelsTouchesInView = true;
|
||||
|
||||
[_view addGestureRecognizer:_zoomGesture];
|
||||
|
||||
[self _applyOptions];
|
||||
}
|
||||
|
||||
-(void)_applyOptions {
|
||||
_osdRenderer.useSingleCrease = _singleCreaseSwitch.isOn;
|
||||
_osdRenderer.usePatchBackfaceCulling = _backpatchCullingSwitch.isOn;
|
||||
_osdRenderer.usePrimitiveBackfaceCulling = _backfaceCullingSwitch.isOn;
|
||||
_osdRenderer.useScreenspaceTessellation = sender.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
|
||||
_osdRenderer.usePatchClipCulling = _patchClipCullingSwitch.isOn;
|
||||
_osdRenderer.useAdaptive = true;
|
||||
_osdRenderer.freeze = true;
|
||||
_osdRenderer.animateVertices = false;
|
||||
|
||||
_osdRenderer.kernelType = kMetal;
|
||||
_osdRenderer.refinementLevel = _refinementStepper.value;
|
||||
_osdRenderer.tessellationLevel = _tessellationStepper.value;
|
||||
_osdRenderer.colorMode = (ColorMode)[_colorModePickerView selectedRowInComponent:0];
|
||||
_osdRenderer.normalMode = (NormalMode)[_normalModePickerView selectedRowInComponent:0];
|
||||
_osdRenderer.displacementMode = (DisplacementMode)[_displacementModePickerView selectedRowInComponent:0];
|
||||
_osdRenderer.mipmapBias = _mipmapBiasSlider.value;
|
||||
_osdRenderer.displacementScale = _displacementSlider.value;
|
||||
|
||||
|
||||
|
||||
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
|
||||
[_tesLvLlabel sizeToFit];
|
||||
|
||||
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
|
||||
[_refLvlLabel sizeToFit];
|
||||
}
|
||||
|
||||
-(void)_zoomView {
|
||||
static float lastY = 0;
|
||||
if(_zoomGesture.state == UIGestureRecognizerStateBegan) {
|
||||
lastY = [_zoomGesture translationInView:_view].y;
|
||||
} else if(_zoomGesture.state == UIGestureRecognizerStateChanged) {
|
||||
const auto currentY = [_zoomGesture translationInView:_view].y;
|
||||
const auto deltaY = (currentY - lastY) / 100.0;
|
||||
lastY = currentY;
|
||||
_osdRenderer.camera->dollyDistance += deltaY;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
_isTouching = true;
|
||||
_startTouch = [touches.anyObject locationInView:self.view];
|
||||
[super touchesBegan:touches withEvent:event];
|
||||
}
|
||||
|
||||
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
_isTouching = false;
|
||||
[super touchesEnded:touches withEvent:event];
|
||||
}
|
||||
|
||||
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
if(_isTouching)
|
||||
{
|
||||
for(UITouch* touch in touches)
|
||||
{
|
||||
CGPoint location = [touch locationInView:self.view];
|
||||
_startTouch = [touch previousLocationInView:self.view];
|
||||
|
||||
double deltaX = location.x - _startTouch.x;
|
||||
double deltaY = location.y - _startTouch.y;
|
||||
|
||||
_osdRenderer.camera->rotationX += deltaX / 5.0;
|
||||
_osdRenderer.camera->rotationY += deltaY / 5.0;
|
||||
}
|
||||
}
|
||||
[super touchesMoved:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
|
||||
return _device;
|
||||
}
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
|
||||
return _commandQueue;
|
||||
}
|
||||
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
|
||||
return _view.currentRenderPassDescriptor;
|
||||
}
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
|
||||
}
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
descriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
|
||||
descriptor.depthAttachmentPixelFormat = _view.depthStencilPixelFormat;
|
||||
descriptor.sampleCount = _view.sampleCount;
|
||||
}
|
||||
- (IBAction)stepperChanged:(UIStepper *)sender {
|
||||
if(sender == _tessellationStepper) {
|
||||
_osdRenderer.tessellationLevel = sender.value;
|
||||
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
|
||||
[_tesLvLlabel sizeToFit];
|
||||
|
||||
} else if (sender == _refinementStepper) {
|
||||
_osdRenderer.refinementLevel = sender.value;
|
||||
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
|
||||
[_refLvlLabel sizeToFit];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)switchChanged:(UISwitch *)sender {
|
||||
if(sender == _wireframeSwitch) {
|
||||
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
|
||||
} else if(sender == _backpatchCullingSwitch) {
|
||||
_osdRenderer.usePatchBackfaceCulling = sender.isOn;
|
||||
} else if(sender == _backfaceCullingSwitch) {
|
||||
_osdRenderer.usePrimitiveBackfaceCulling = sender.isOn;
|
||||
} else if(sender == _patchClipCullingSwitch) {
|
||||
_osdRenderer.usePatchClipCulling = sender.isOn;
|
||||
} else if(sender == _singleCreaseSwitch) {
|
||||
_osdRenderer.useSingleCrease = sender.isOn;
|
||||
} else if(sender == _screenspaceTessellationSwitch) {
|
||||
_osdRenderer.useScreenspaceTessellation = sender.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)sliderChanged:(UISlider *)sender {
|
||||
if(sender == _displacementSlider) {
|
||||
_osdRenderer.displacementScale = sender.value;
|
||||
} else if(sender == _mipmapBiasSlider) {
|
||||
_osdRenderer.mipmapBias = sender.value;
|
||||
}
|
||||
}
|
||||
|
||||
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
|
||||
if(pickerView == _colorModePickerView) {
|
||||
return 8;
|
||||
} else if(pickerView == _normalModePickerView) {
|
||||
return 5;
|
||||
} else if(pickerView == _displacementModePickerView) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
|
||||
if(pickerView == _colorModePickerView) {
|
||||
switch(row) {
|
||||
case kColorModePtexNearest: return @"Ptex Nearest";
|
||||
case kColorModeNormal: return @"Normal";
|
||||
case kColorModeNone: return @"None";
|
||||
case kColorModePatchType: return @"Patch Type";
|
||||
case kColorModePatchCoord: return @"Patch Coord";
|
||||
case kColorModePtexBilinear: return @"Ptex Bilinear";
|
||||
case kColorModePtexHWBilinear: return @"Ptex HW Bilinear";
|
||||
case kColorModePtexBiQuadratic: return @"Ptex BiQuadratic";
|
||||
}
|
||||
} else if(pickerView == _normalModePickerView) {
|
||||
switch(row) {
|
||||
case kNormalModeSurface: return @"Surface";
|
||||
case kNormalModeBiQuadratic: return @"BiQuadratic";
|
||||
case kNormalModeScreenspace: return @"Screenspace";
|
||||
case kNormalModeBiQuadraticWG: return @"BiQuadratic WG";
|
||||
case kNormalModeHWScreenspace: return @"HW Screenspace";
|
||||
}
|
||||
} else if(pickerView == _displacementModePickerView) {
|
||||
switch (row) {
|
||||
case kDisplacementModeBilinear: return @"Bilinear";
|
||||
case KDisplacementModeNone: return @"None";
|
||||
case kDisplacementModeHWBilinear: return @"HW Bilinear";
|
||||
case kDisplacementModeBiQuadratic: return @"BiQuadratic";
|
||||
}
|
||||
}
|
||||
return @"";
|
||||
}
|
||||
|
||||
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
||||
if(pickerView == _colorModePickerView) {
|
||||
_osdRenderer.colorMode = (ColorMode)row;
|
||||
} else if(pickerView == _normalModePickerView) {
|
||||
_osdRenderer.normalMode = (NormalMode)row;
|
||||
} else if(pickerView == _displacementModePickerView) {
|
||||
_osdRenderer.displacementMode = (DisplacementMode)row;
|
||||
}
|
||||
}
|
||||
@end
|
8
examples/mtlPtexViewer/iOS/main.m
Normal file
8
examples/mtlPtexViewer/iOS/main.m
Normal file
@ -0,0 +1,8 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
122
examples/mtlPtexViewer/init_shapes.h
Normal file
122
examples/mtlPtexViewer/init_shapes.h
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../../regression/common/shape_utils.h"
|
||||
#include "../../regression/shapes/all.h"
|
||||
|
||||
struct ShapeDesc {
|
||||
|
||||
ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme,
|
||||
bool iIsLeftHanded = false) :
|
||||
name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { }
|
||||
|
||||
std::string name,
|
||||
data;
|
||||
Scheme scheme;
|
||||
bool isLeftHanded;
|
||||
};
|
||||
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
// g_defaultShapes.push_back(ShapeDesc("temple", Viewer::shapes::temple, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fan", catmark_fan, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_flap", catmark_flap, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_flap2", catmark_flap2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark));
|
||||
// g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases1", catmark_tent_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_tent", catmark_tent, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark));
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) );
|
||||
// // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) );
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
//
|
||||
// g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
//
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole8", loop_pole8, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
// g_defaultShapes.push_back(ShapeDesc("loop_pole360", loop_pole360, kLoop));
|
||||
}
|
107
examples/mtlPtexViewer/mtlPtexViewer.h
Normal file
107
examples/mtlPtexViewer/mtlPtexViewer.h
Normal file
@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
typedef enum {
|
||||
kCPU = 0,
|
||||
kMetal,
|
||||
} KernelType;
|
||||
|
||||
typedef enum {
|
||||
kDisplacementModeHWBilinear = 0,
|
||||
kDisplacementModeBilinear,
|
||||
kDisplacementModeBiQuadratic,
|
||||
kDisplacementModeNone
|
||||
} DisplacementMode;
|
||||
|
||||
typedef enum {
|
||||
kNormalModeHWScreenspace = 0,
|
||||
kNormalModeScreenspace,
|
||||
kNormalModeBiQuadratic,
|
||||
kNormalModeBiQuadraticWG,
|
||||
kNormalModeSurface
|
||||
} NormalMode;
|
||||
|
||||
typedef enum {
|
||||
kDisplayStyleWire = 0,
|
||||
kDisplayStyleShaded,
|
||||
kDisplayStyleWireOnShaded,
|
||||
} DisplayStyle;
|
||||
|
||||
typedef enum {
|
||||
kColorModePtexNearest = 0,
|
||||
kColorModePtexBilinear,
|
||||
kColorModePtexHWBilinear,
|
||||
kColorModePtexBiQuadratic,
|
||||
kColorModePatchType,
|
||||
kColorModePatchCoord,
|
||||
kColorModeNormal,
|
||||
kColorModeNone
|
||||
} ColorMode;
|
||||
|
||||
typedef struct {
|
||||
float rotationX;
|
||||
float rotationY;
|
||||
float dollyDistance;
|
||||
float aspectRatio;
|
||||
} Camera;
|
||||
|
||||
@class OSDRenderer;
|
||||
|
||||
@protocol OSDRendererDelegate <NSObject>
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer*)renderer;
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer*)renderer;
|
||||
-(MTLRenderPassDescriptor*)renderPassDescriptorFor:(OSDRenderer*)renderer;
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor*)descriptor for:(OSDRenderer*)renderer;
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor*)descriptor for:(OSDRenderer*)renderer;
|
||||
@end
|
||||
|
||||
@interface OSDRenderer : NSObject
|
||||
|
||||
-(instancetype)initWithDelegate:(id<OSDRendererDelegate>)delegate;
|
||||
|
||||
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
|
||||
|
||||
@property (nonatomic) unsigned refinementLevel;
|
||||
@property (nonatomic) float tessellationLevel;
|
||||
|
||||
@property (readonly, nonatomic) NSArray<NSString*>* loadedModels;
|
||||
@property (nonatomic) NSString* currentModel;
|
||||
|
||||
@property (readonly, nonatomic) Camera* camera;
|
||||
|
||||
|
||||
@property (nonatomic) bool useSeamlessMipmap;
|
||||
@property (nonatomic) bool useFractionalTessellation;
|
||||
@property (nonatomic) bool useScreenspaceTessellation;
|
||||
@property (nonatomic) bool usePatchIndexBuffer;
|
||||
@property (nonatomic) bool usePatchBackfaceCulling;
|
||||
@property (nonatomic) bool usePatchClipCulling;
|
||||
@property (nonatomic) bool useSingleCrease;
|
||||
@property (nonatomic) bool useInfinitelySharpPatch;
|
||||
@property (nonatomic) bool useStageIn;
|
||||
@property (nonatomic) bool usePrimitiveBackfaceCulling;
|
||||
@property (nonatomic) bool useAdaptive;
|
||||
@property (nonatomic) bool freeze;
|
||||
@property (nonatomic) bool animateVertices;
|
||||
@property (nonatomic) bool displayControlMeshEdges;
|
||||
@property (nonatomic) bool displayControlMeshVertices;
|
||||
@property (nonatomic) bool displaySpecular;
|
||||
@property (nonatomic) bool displayOcclusion;
|
||||
@property (nonatomic) float mipmapBias;
|
||||
@property (nonatomic) float displacementScale;
|
||||
|
||||
@property (nonatomic) NSString* ptexColorFilename;
|
||||
@property (nonatomic) NSString* ptexDisplacementFilename;
|
||||
@property (nonatomic) NSString* ptexOcclusionFilename;
|
||||
@property (nonatomic) NSString* ptexSpecularFilename;
|
||||
|
||||
@property (nonatomic) ColorMode colorMode;
|
||||
@property (nonatomic) NormalMode normalMode;
|
||||
@property (nonatomic) DisplacementMode displacementMode;
|
||||
@property (nonatomic) DisplayStyle displayStyle;
|
||||
@property (nonatomic) KernelType kernelType;
|
||||
@end
|
697
examples/mtlPtexViewer/mtlPtexViewer.metal
Normal file
697
examples/mtlPtexViewer/mtlPtexViewer.metal
Normal file
@ -0,0 +1,697 @@
|
||||
#line 0 "examples/mtlPtexViewer/mtlPtexViewer.metal"
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct Config {
|
||||
float displacementScale;
|
||||
float mipmapBias;
|
||||
};
|
||||
|
||||
struct PerFrameConstants {
|
||||
float4x4 ModelViewMatrix;
|
||||
float4x4 ProjectionMatrix;
|
||||
float4x4 ModelViewProjectionMatrix;
|
||||
float4x4 ModelViewInverseMatrix;
|
||||
float TessLevel;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const constant float4 patchColors[] = {
|
||||
float4(1.0f, 1.0f, 1.0f, 1.0f), // regular
|
||||
float4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
|
||||
float4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
|
||||
float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
|
||||
float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
|
||||
float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
|
||||
|
||||
float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
|
||||
float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
|
||||
float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
|
||||
float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
|
||||
float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
|
||||
float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
|
||||
|
||||
float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
|
||||
float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
|
||||
float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
|
||||
float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
|
||||
float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
|
||||
float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
|
||||
|
||||
float4(0.0f, 1.0f, 0.0f, 1.0f), // corner
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
|
||||
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f) // gregory basis
|
||||
};
|
||||
|
||||
float4
|
||||
getAdaptivePatchColor(int3 patchParam, float sharpness)
|
||||
{
|
||||
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
|
||||
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
|
||||
|
||||
int patchType = 0;
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
if (sharpness > 0) {
|
||||
pattern = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (edgeCount == 1) {
|
||||
patchType = 2; // BOUNDARY
|
||||
}
|
||||
if (edgeCount == 2) {
|
||||
patchType = 3; // CORNER
|
||||
}
|
||||
|
||||
// XXX: it looks like edgeCount != 0 for some gregory boundary patches.
|
||||
// there might be a bug somewhere...
|
||||
#if OSD_PATCH_GREGORY
|
||||
patchType = 4;
|
||||
#elif OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchType = 5;
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
patchType = 6;
|
||||
#endif
|
||||
|
||||
return patchColors[6*patchType + pattern];
|
||||
}
|
||||
|
||||
#if DISPLACEMENT_HW_BILINEAR \
|
||||
|| DISPLACEMENT_BILINEAR \
|
||||
|| DISPLACEMENT_BIQUADRATIC \
|
||||
|| NORMAL_HW_SCREENSPACE \
|
||||
|| NORMAL_SCREENSPACE \
|
||||
|| NORMAL_BIQUADRATIC \
|
||||
|| NORMAL_BIQUADRATIC_WG
|
||||
#define USE_DISPLACEMENT_RESOURCES 1
|
||||
#endif
|
||||
|
||||
#if DISPLACEMENT_HW_BILINEAR \
|
||||
|| DISPLACEMENT_BILINEAR \
|
||||
|| DISPLACEMENT_BIQUADRATIC
|
||||
|
||||
#define USE_DISPLACEMENT 1
|
||||
#undef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK \
|
||||
|
||||
float3 displacement(float3 position, float3 normal, float4 patchCoord, float mipmapBias, float displacementScale
|
||||
#if USE_DISPLACEMENT_RESOURCES
|
||||
,texture2d_array<float, access::sample> textureDisplace_Data
|
||||
,device ushort* textureDisplace_Packing
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if DISPLACEMENT_HW_BILINEAR
|
||||
float disp = PtexLookupFast(patchCoord, mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing).x;
|
||||
#elif DISPLACEMENT_BILINEAR
|
||||
float disp = PtexMipmapLookup(patchCoord, mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing).x;
|
||||
#elif DISPLACEMENT_BIQUADRATIC
|
||||
float disp = PtexMipmapLookupQuadratic(patchCoord, mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing).x;
|
||||
#else
|
||||
float disp(0);
|
||||
#endif
|
||||
return position + disp*normal * displacementScale;
|
||||
}
|
||||
#endif
|
||||
|
||||
float4 GeneratePatchCoord(float2 uv, int3 patchParam) // for non-adaptive
|
||||
{
|
||||
return OsdInterpolatePatchCoord(uv, patchParam);
|
||||
}
|
||||
|
||||
#if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE
|
||||
|
||||
float3
|
||||
perturbNormalFromDisplacement(float3 position, float3 normal, float4 patchCoord, float mipmapBias
|
||||
,texture2d_array<float, access::sample> textureDisplace_Data
|
||||
,device ushort* textureDisplace_Packing
|
||||
,float displacementScale)
|
||||
{
|
||||
// by Morten S. Mikkelsen
|
||||
// http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
|
||||
// slightly modified for ptex guttering
|
||||
float3 vSigmaS = dfdx(position);
|
||||
float3 vSigmaT = dfdy(position);
|
||||
float3 vN = normal;
|
||||
float3 vR1 = cross(vSigmaT, vN);
|
||||
float3 vR2 = cross(vN, vSigmaS);
|
||||
float fDet = dot(vSigmaS, vR1);
|
||||
#if 0
|
||||
// not work well with ptex
|
||||
float dBs = dfdx(disp);
|
||||
float dBt = dfdy(disp);
|
||||
#else
|
||||
float2 texDx = dfdx(patchCoord.xy);
|
||||
float2 texDy = dfdy(patchCoord.xy);
|
||||
|
||||
// limit forward differencing to the width of ptex gutter
|
||||
const float resolution = 128.0;
|
||||
float d = min(1.0f, (0.5/resolution)/max(length(texDx), length(texDy)));
|
||||
|
||||
float4 STll = patchCoord;
|
||||
float4 STlr = patchCoord + d * float4(texDx.x, texDx.y, 0, 0);
|
||||
float4 STul = patchCoord + d * float4(texDy.x, texDy.y, 0, 0);
|
||||
#if NORMAL_HW_SCREENSPACE
|
||||
float Hll = PtexLookupFast(STll, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
float Hlr = PtexLookupFast(STlr, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
float Hul = PtexLookupFast(STul, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
#elif NORMAL_SCREENSPACE
|
||||
float Hll = PtexMipmapLookup(STll, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
float Hlr = PtexMipmapLookup(STlr, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
float Hul = PtexMipmapLookup(STul, mipmapBias, textureDisplace_Data, textureDisplace_Packing).x * displacementScale;
|
||||
#endif
|
||||
float dBs = (Hlr - Hll)/d;
|
||||
float dBt = (Hul - Hll)/d;
|
||||
#endif
|
||||
|
||||
float3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
|
||||
return normalize(abs(fDet) * vN - vSurfGrad);
|
||||
}
|
||||
#endif // NORMAL_SCREENSPACE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct FragmentInput
|
||||
{
|
||||
float4 positionOut [[position]];
|
||||
float3 position;
|
||||
float3 normal;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 patchCoord;
|
||||
#if COLOR_PATCHTYPE
|
||||
float4 patchColor;
|
||||
#endif
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
float3 Nu;
|
||||
float3 Nv;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if OSD_IS_ADAPTIVE
|
||||
#if USE_STAGE_IN
|
||||
#if OSD_PATCH_REGULAR
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float3 P1 [[attribute(1)]];
|
||||
float3 P2 [[attribute(2)]];
|
||||
#if !USE_PTVS_SHARPNESS
|
||||
float2 vSegments [[attribute(3)]];
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo [[attribute(5)]];
|
||||
float4 tessOuterHi [[attribute(6)]];
|
||||
#endif
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
float3 Ep [[attribute(1)]];
|
||||
float3 Em [[attribute(2)]];
|
||||
float3 Fp [[attribute(3)]];
|
||||
float3 Fm [[attribute(4)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
struct ControlPoint
|
||||
{
|
||||
float3 position [[attribute(0)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
kernel void compute_main(
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
unsigned thread_position_in_grid [[thread_position_in_grid]],
|
||||
unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]],
|
||||
unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]],
|
||||
OsdPatchParamBufferSet osdBuffers,
|
||||
device MTLQuadTessellationFactorsHalf* quadTessellationFactors [[buffer(QUAD_TESSFACTORS_INDEX)]]
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
,device unsigned* patchIndex [[buffer(OSD_PATCH_INDEX_BUFFER_INDEX)]]
|
||||
,device MTLDrawPatchIndirectArguments* drawIndirectCommands [[buffer(OSD_DRAWINDIRECT_BUFFER_INDEX)]]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
threadgroup int3 patchParam[PATCHES_PER_THREADGROUP];
|
||||
threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH];
|
||||
|
||||
const auto real_threadgroup = thread_position_in_grid / REAL_THREADGROUP_DIVISOR;
|
||||
const auto subthreadgroup_in_threadgroup = thread_position_in_threadgroup / REAL_THREADGROUP_DIVISOR;
|
||||
const auto real_thread_in_threadgroup = thread_position_in_threadgroup & (REAL_THREADGROUP_DIVISOR - 1);
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
const auto validThread = thread_position_in_grid * CONTROL_POINTS_PER_THREAD < osdBuffers.kernelExecutionLimit;
|
||||
#else
|
||||
const auto validThread = true;
|
||||
if(thread_position_in_grid * CONTROL_POINTS_PER_THREAD >= osdBuffers.kernelExecutionLimit)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(validThread)
|
||||
{
|
||||
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
|
||||
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
{
|
||||
const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride];
|
||||
const auto v = osdBuffers.vertexBuffer[vertexId];
|
||||
|
||||
threadgroup auto& patchVertex = patchVertices[thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset];
|
||||
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
|
||||
//User per vertex goes here, modifying 'patchVertex'
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread)
|
||||
{
|
||||
#if PATCHES_PER_THREADGROUP > 1
|
||||
auto patch = patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_THREAD * CONTROL_POINTS_PER_PATCH;
|
||||
#else
|
||||
//Small optimization for the '1 patch per threadgroup' case
|
||||
auto patch = patchVertices;
|
||||
#endif
|
||||
|
||||
if(!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
|
||||
{
|
||||
#if !OSD_USE_PATCH_INDEX_BUFFER
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[1] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[2] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[3] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[1] = 0.0h;
|
||||
#endif
|
||||
|
||||
patchParam[subthreadgroup_in_threadgroup].z = -1;
|
||||
#if !NEEDS_BARRIER
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread && patchParam[subthreadgroup_in_threadgroup].z != -1)
|
||||
{
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
{
|
||||
OsdComputePerPatchVertex(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
real_thread_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
real_threadgroup,
|
||||
thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_device_and_threadgroup);
|
||||
#endif
|
||||
|
||||
if(validThread && real_thread_in_threadgroup == 0)
|
||||
{
|
||||
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed);
|
||||
patchIndex[patchId] = real_threadgroup;
|
||||
#else
|
||||
const auto patchId = real_threadgroup;
|
||||
#endif
|
||||
|
||||
OsdComputePerPatchFactors(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
frameConsts.TessLevel,
|
||||
real_threadgroup,
|
||||
frameConsts.ProjectionMatrix,
|
||||
frameConsts.ModelViewMatrix,
|
||||
osdBuffers,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
quadTessellationFactors[patchId]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]]
|
||||
vertex FragmentInput vertex_main(
|
||||
const constant Config& config [[buffer(CONFIG_BUFFER_INDEX)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
#if USE_STAGE_IN
|
||||
const PatchInput patchInput [[stage_in]],
|
||||
#else
|
||||
const OsdVertexBufferSet patchInput,
|
||||
#endif
|
||||
float2 position_in_patch [[position_in_patch]],
|
||||
uint patch_id [[patch_id]]
|
||||
#if USE_DISPLACEMENT_RESOURCES
|
||||
,texture2d_array<float, access::sample> textureDisplace_Data [[texture(DISPLACEMENT_TEXTURE_INDEX)]]
|
||||
,device ushort* textureDisplace_Packing [[buffer(DISPLACEMENT_BUFFER_INDEX)]]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
FragmentInput out;
|
||||
|
||||
#if USE_STAGE_IN
|
||||
int3 patchParam = patchInput.patchParam;
|
||||
#else
|
||||
int3 patchParam = patchInput.patchParamBuffer[patch_id];
|
||||
#endif
|
||||
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
|
||||
exp2((float)refinementLevel - 1);
|
||||
|
||||
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
|
||||
|
||||
|
||||
#if USE_DISPLACEMENT
|
||||
float3 position = displacement(patchVertex.position,
|
||||
patchVertex.normal,
|
||||
patchVertex.patchCoord,
|
||||
config.mipmapBias,
|
||||
config.displacementScale
|
||||
#if USE_DISPLACEMENT_RESOURCES
|
||||
,textureDisplace_Data, textureDisplace_Packing
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
float3 position = patchVertex.position;
|
||||
#endif
|
||||
|
||||
|
||||
out.positionOut = mul(frameConsts.ModelViewProjectionMatrix, float4(position, 1));
|
||||
out.position = mul(frameConsts.ModelViewMatrix, float4(position,1)).xyz;
|
||||
out.normal = mul(frameConsts.ModelViewMatrix,float4(patchVertex.normal, 0)).xyz;
|
||||
out.tangent = mul(frameConsts.ModelViewMatrix,float4(patchVertex.tangent,0)).xyz;
|
||||
out.bitangent = mul(frameConsts.ModelViewMatrix,float4(patchVertex.bitangent,0)).xyz;
|
||||
out.patchCoord = patchVertex.patchCoord;
|
||||
#if COLOR_PATCHTYPE
|
||||
out.patchColor = getAdaptivePatchColor(patchParam, OsdGetPatchSharpness(patchParam));
|
||||
#endif
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
out.Nu = mul(frameConsts.ModelViewMatrix, float4(patchVertex.Nu, 0)).xyz;
|
||||
out.Nv = mul(frameConsts.ModelViewMatrix, float4(patchVertex.Nv, 0)).xyz;
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
const constant float VIEWPORT_SCALE = 1024.0; // XXXdyu
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Lighting
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define NUM_LIGHTS 1
|
||||
|
||||
struct LightSource {
|
||||
float4 position;
|
||||
float4 ambient;
|
||||
float4 diffuse;
|
||||
float4 specular;
|
||||
};
|
||||
|
||||
float4
|
||||
lighting(float4 texColor, float3 Peye, float3 Neye, float occ, const constant LightSource (&lightSource)[NUM_LIGHTS])
|
||||
{
|
||||
float4 color = float4(0.0, 0.0, 0.0, 0.0);
|
||||
float3 n = Neye;
|
||||
|
||||
for (int i = 0; i < NUM_LIGHTS; ++i) {
|
||||
|
||||
float4 Plight = lightSource[i].position;
|
||||
float3 l = (Plight.w == 0.0)
|
||||
? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
|
||||
|
||||
float3 h = normalize(l + float3(0,0,1)); // directional viewer
|
||||
|
||||
float d = max(0.0, dot(n, l));
|
||||
float s = pow(max(0.0, dot(n, h)), 64.0f);
|
||||
|
||||
color += (1.0 - occ) * ((lightSource[i].ambient +
|
||||
d * lightSource[i].diffuse) * texColor +
|
||||
s * lightSource[i].specular);
|
||||
}
|
||||
|
||||
color.a = 1.0;
|
||||
return color;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pixel Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
float4
|
||||
edgeColor(float4 Cfill, float4 edgeDistance)
|
||||
{
|
||||
#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
|
||||
#ifdef PRIM_TRI
|
||||
float d =
|
||||
min(edgeDistance[0], min(edgeDistance[1], edgeDistance[2]));
|
||||
#endif
|
||||
#ifdef PRIM_QUAD
|
||||
float d =
|
||||
min(min(edgeDistance[0], edgeDistance[1]),
|
||||
min(edgeDistance[2], edgeDistance[3]));
|
||||
#endif
|
||||
float4 Cedge = float4(1.0, 1.0, 0.0, 1.0);
|
||||
float p = exp2(-2 * d * d);
|
||||
|
||||
#if defined(GEOMETRY_OUT_WIRE)
|
||||
if (p < 0.25) discard;
|
||||
#endif
|
||||
|
||||
Cfill.rgb = lerp(Cfill.rgb, Cedge.rgb, p);
|
||||
#endif
|
||||
return Cfill;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pixel Shader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#if COLOR_PTEX_NEAREST || \
|
||||
COLOR_PTEX_HW_BILINEAR || \
|
||||
COLOR_PTEX_BILINEAR || \
|
||||
COLOR_PTEX_BIQUADRATIC
|
||||
#define USE_IMAGE_RESOURCES 1
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
#define USE_OCCLUSION_RESOURCES 1
|
||||
#endif
|
||||
|
||||
#if USE_PTEX_SPECULAR
|
||||
#define USE_SPECULAR_RESOURCES 1
|
||||
#endif
|
||||
|
||||
fragment float4 fragment_main(
|
||||
FragmentInput input [[stage_in]]
|
||||
#if USE_DISPLACEMENT_RESOURCES
|
||||
,texture2d_array<float, access::sample> textureDisplace_Data [[texture(DISPLACEMENT_TEXTURE_INDEX)]]
|
||||
,device ushort* textureDisplace_Packing [[buffer(DISPLACEMENT_BUFFER_INDEX)]]
|
||||
#endif
|
||||
#if USE_IMAGE_RESOURCES
|
||||
,texture2d_array<float, access::sample> textureImage_Data [[texture(IMAGE_TEXTURE_INDEX)]]
|
||||
,device ushort* textureImage_Packing [[buffer(IMAGE_BUFFER_INDEX)]]
|
||||
#endif
|
||||
#if USE_OCCLUSION_RESOURCES
|
||||
,texture2d_array<float, access::sample> textureOcclusion_Data [[texture(OCCLUSION_TEXTURE_INDEX)]]
|
||||
,device ushort* textureOcclusion_Packing [[buffer(OCCLUSION_BUFFER_INDEX)]]
|
||||
#endif
|
||||
#if USE_SPECULAR_RESOURCES
|
||||
,texture2d_array<float, acess::read> textureSpecular_Data [[texture(SPECULAR_TEXTURE_INDEX)]]
|
||||
,device ushort* textureSpecular_Packing [[buffer(SPECULAR_BUFFER_INDEX)]]
|
||||
#endif
|
||||
,const constant LightSource (&lightSource [[buffer(0)]]) [NUM_LIGHTS]
|
||||
,const constant Config& config [[buffer(1)]]
|
||||
,const constant float4& shade [[buffer(2)]]
|
||||
)
|
||||
{
|
||||
const auto displacementScale = config.displacementScale;
|
||||
const auto mipmapBias = config.mipmapBias;
|
||||
float4 outColor;
|
||||
// ------------ normal ---------------
|
||||
#if NORMAL_HW_SCREENSPACE || NORMAL_SCREENSPACE
|
||||
float3 normal = perturbNormalFromDisplacement(input.position.xyz,
|
||||
input.normal,
|
||||
input.patchCoord,
|
||||
config.mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing,
|
||||
config.displacementScale);
|
||||
#elif NORMAL_BIQUADRATIC || NORMAL_BIQUADRATIC_WG
|
||||
float4 du, dv;
|
||||
float4 disp = PtexMipmapLookupQuadratic(du, dv, input.patchCoord,
|
||||
config.mipmapBias,
|
||||
textureDisplace_Data,
|
||||
textureDisplace_Packing);
|
||||
|
||||
disp *= displacementScale;
|
||||
du *= displacementScale;
|
||||
dv *= displacementScale;
|
||||
|
||||
float3 n = normalize(cross(input.tangent, input.bitangent));
|
||||
float3 tangent = input.tangent + n * du.x;
|
||||
float3 bitangent = input.bitangent + n * dv.x;
|
||||
|
||||
#if NORMAL_BIQUADRATIC_WG
|
||||
tangent += input.Nu * disp.x;
|
||||
bitangent += input.Nv * disp.x;
|
||||
#endif
|
||||
|
||||
float3 normal = normalize(cross(tangent, bitangent));
|
||||
#else
|
||||
float3 normal = input.normal;
|
||||
#endif
|
||||
|
||||
// ------------ color ---------------
|
||||
#if COLOR_PTEX_NEAREST
|
||||
float4 texColor = PtexLookupNearest(input.patchCoord,
|
||||
textureImage_Data,
|
||||
textureImage_Packing);
|
||||
#elif COLOR_PTEX_HW_BILINEAR
|
||||
float4 texColor = PtexLookupFast(input.patchCoord,
|
||||
textureImage_Data,
|
||||
textureImage_Packing);
|
||||
#elif COLOR_PTEX_BILINEAR
|
||||
float4 texColor = PtexMipmapLookup(input.patchCoord, mipmapBias,
|
||||
textureImage_Data,
|
||||
textureImage_Packing);
|
||||
#elif COLOR_PTEX_BIQUADRATIC
|
||||
float4 texColor = PtexMipmapLookupQuadratic(input.patchCoord, mipmapBias,
|
||||
textureImage_Data,
|
||||
textureImage_Packing);
|
||||
#elif COLOR_PATCHTYPE
|
||||
float4 texColor = lighting(float4(input.patchColor), input.position.xyz, normal, 0, lightSource);
|
||||
outColor = texColor;
|
||||
return outColor;
|
||||
#elif COLOR_PATCHCOORD
|
||||
float4 texColor = lighting(input.patchCoord, input.position.xyz, normal, 0, lightSource);
|
||||
outColor = texColor;
|
||||
return outColor;
|
||||
#elif COLOR_NORMAL
|
||||
float4 texColor = float4(normal.x, normal.y, normal.z, 1);
|
||||
outColor = texColor;
|
||||
return outColor;
|
||||
#else // COLOR_NONE
|
||||
float4 texColor = float4(0.5, 0.5, 0.5, 1);
|
||||
#endif
|
||||
|
||||
// ------------ occlusion ---------------
|
||||
|
||||
#if USE_PTEX_OCCLUSION
|
||||
float occ = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
|
||||
textureOcclusion_Data,
|
||||
textureOcclusion_Packing).x;
|
||||
#else
|
||||
float occ = 0.0;
|
||||
#endif
|
||||
|
||||
// ------------ specular ---------------
|
||||
|
||||
#if USE_PTEX_SPECULAR
|
||||
float specular = PtexMipmapLookup(input.patchCoord, config.mipmapBias,
|
||||
textureSpecular_Data,
|
||||
textureSpecular_Packing).x;
|
||||
#else
|
||||
float specular = 1.0;
|
||||
#endif
|
||||
// ------------ lighting ---------------
|
||||
float4 Cf = lighting(texColor, input.position.xyz, normal, occ, lightSource);
|
||||
|
||||
// ------------ wireframe ---------------
|
||||
outColor = max(Cf, shade);
|
||||
return outColor;
|
||||
}
|
1281
examples/mtlPtexViewer/mtlPtexViewer.mm
Normal file
1281
examples/mtlPtexViewer/mtlPtexViewer.mm
Normal file
File diff suppressed because it is too large
Load Diff
115
examples/mtlViewer/CMakeLists.txt
Normal file
115
examples/mtlViewer/CMakeLists.txt
Normal file
@ -0,0 +1,115 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
# with the following modification; you may not use this file except in
|
||||
# compliance with the Apache License and the following modification to it:
|
||||
# Section 6. Trademarks. is deleted and replaced with:
|
||||
#
|
||||
# 6. Trademarks. This License does not grant permission to use the trade
|
||||
# names, trademarks, service marks, or product names of the Licensor
|
||||
# and its affiliates, except as required to comply with Section 4(c) of
|
||||
# the License and to reproduce the content of the NOTICE file.
|
||||
#
|
||||
# You may obtain a copy of the Apache License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the Apache License with the above modification is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the Apache License for the specific
|
||||
# language governing permissions and limitations under the Apache License.
|
||||
#
|
||||
|
||||
# *** mtlViewer ***
|
||||
|
||||
if(IOS)
|
||||
set(BUNDLE_FILES
|
||||
"iOS/Base.lproj/LaunchScreen.storyboard"
|
||||
"iOS/Base.lproj/Main.storyboard"
|
||||
)
|
||||
set(PLATFORM_PLIST "iOS/Info.plist")
|
||||
set(PLATFORM_FILES
|
||||
"iOS/AppDelegate.h"
|
||||
"iOS/AppDelegate.m"
|
||||
"iOS/main.m"
|
||||
"iOS/ViewController.h"
|
||||
"iOS/ViewController.mm"
|
||||
)
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"-framework UIKit"
|
||||
)
|
||||
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
else()
|
||||
set(BUNDLE_FILES
|
||||
"OSX/MainMenu.xib"
|
||||
)
|
||||
set(PLATFORM_PLIST "OSX/Info.plist")
|
||||
set(PLATFORM_FILES
|
||||
"OSX/AppDelegate.h"
|
||||
"OSX/AppDelegate.m"
|
||||
"OSX/main.m"
|
||||
"OSX/ViewController.h"
|
||||
"OSX/ViewController.mm"
|
||||
)
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"-framework OpenGL"
|
||||
"-framework AppKit"
|
||||
)
|
||||
set_source_files_properties("${BUNDLE_FILES}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"${OPENSUBDIV_INCLUDE_DIR}"
|
||||
"${METAL_INCLUDE_DIR}"
|
||||
)
|
||||
|
||||
list(APPEND PLATFORM_FILES
|
||||
"mtlViewer.h"
|
||||
"mtlViewer.mm"
|
||||
)
|
||||
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"osd_static_framework"
|
||||
"${METAL_LIBRARY}"
|
||||
"-framework MetalKit"
|
||||
"-framework Foundation"
|
||||
"-framework QuartzCore"
|
||||
)
|
||||
|
||||
_stringify("mtlViewer.metal" INC_FILES)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
_add_executable(mtlViewer "examples/mtlViewer"
|
||||
MACOSX_BUNDLE
|
||||
"${PLATFORM_FILES}"
|
||||
"${INC_FILES}"
|
||||
"${BUNDLE_FILES}"
|
||||
$<TARGET_OBJECTS:regression_common_obj>
|
||||
$<TARGET_OBJECTS:regression_far_utils_obj>
|
||||
$<TARGET_OBJECTS:examples_common_obj>
|
||||
)
|
||||
|
||||
|
||||
set_target_properties (mtlViewer PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
RESOURCE "${BUNDLE_FILES}"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_LIST_DIR}/${PLATFORM_PLIST}"
|
||||
)
|
||||
|
||||
if(IOS)
|
||||
set_target_properties(mtlViewer PROPERTIES
|
||||
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
set_property (TARGET mtlViewer PROPERTY CXX_STANDARD 14)
|
||||
|
||||
target_link_libraries(mtlViewer
|
||||
${PLATFORM_LIBRARIES}
|
||||
)
|
||||
|
||||
install(TARGETS mtlViewer DESTINATION "${CMAKE_BINDIR_BASE}")
|
32
examples/mtlViewer/OSX/AppDelegate.h
Normal file
32
examples/mtlViewer/OSX/AppDelegate.h
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
|
||||
@end
|
||||
|
44
examples/mtlViewer/OSX/AppDelegate.m
Normal file
44
examples/mtlViewer/OSX/AppDelegate.m
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import <MetalKit/MetalKit.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
@end
|
58
examples/mtlViewer/OSX/AppIcon.appiconset/Contents.json
Normal file
58
examples/mtlViewer/OSX/AppIcon.appiconset/Contents.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
34
examples/mtlViewer/OSX/Info.plist
Normal file
34
examples/mtlViewer/OSX/Info.plist
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2016 Apple. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
</dict>
|
||||
</plist>
|
686
examples/mtlViewer/OSX/MainMenu.xib
Normal file
686
examples/mtlViewer/OSX/MainMenu.xib
Normal file
@ -0,0 +1,686 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16C20" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="aZQ-9t-9YL" id="ke3-sq-jK1"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="aZQ-9t-9YL" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="Test" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Test" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About NewApplication" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide NewApplication" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit NewApplication" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="KaW-ft-85H">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="jxT-CU-nIS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
||||
<items>
|
||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="Fal-I4-PZk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="J5U-5w-g23">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="YGs-j5-SAR">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="Lbh-J2-qVU">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="jFq-tB-4Kx">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="Nop-cj-93Q">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="BgM-ve-c93">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="RB4-Sm-HuC">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="NewApplication Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hasShadow="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="1920" height="1080"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO" customClass="OSDView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<connections>
|
||||
<outlet property="menu" destination="AYu-sK-qS6" id="0eg-gK-PK4"/>
|
||||
</connections>
|
||||
</view>
|
||||
<point key="canvasLocation" x="172" y="11"/>
|
||||
</window>
|
||||
<viewController id="tdF-Vh-f4K" customClass="ViewController">
|
||||
<connections>
|
||||
<outlet property="view" destination="se5-gp-TjO" id="fc1-e3-wEk"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
</document>
|
44
examples/mtlViewer/OSX/ViewController.h
Normal file
44
examples/mtlViewer/OSX/ViewController.h
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "../mtlViewer.h"
|
||||
#import "../../common/mtlHud.h"
|
||||
@class ViewController;
|
||||
|
||||
@interface OSDView : MTKView {
|
||||
@public
|
||||
MTLhud hud;
|
||||
}
|
||||
@property (nonatomic) ViewController* controller;
|
||||
@end
|
||||
|
||||
@interface ViewController : NSViewController<MTKViewDelegate, OSDRendererDelegate>
|
||||
@property (weak) IBOutlet OSDView *view;
|
||||
@property (nonatomic) OSDRenderer* osdRenderer;
|
||||
|
||||
|
||||
@end
|
447
examples/mtlViewer/OSX/ViewController.mm
Normal file
447
examples/mtlViewer/OSX/ViewController.mm
Normal file
@ -0,0 +1,447 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
|
||||
#import "ViewController.h"
|
||||
#import <far/patchDescriptor.h>
|
||||
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
|
||||
enum {
|
||||
kHUD_CB_DISPLAY_CONTROL_MESH_EDGES,
|
||||
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS,
|
||||
kHUD_CB_ANIMATE_VERTICES,
|
||||
kHUD_CB_DISPLAY_PATCH_COLOR, //Unused
|
||||
kHUD_CB_DISPLAY_PATCH_CVs, //Unused
|
||||
kHUD_CB_VIEW_LOD,
|
||||
kHUD_CB_FRACTIONAL_SPACING,
|
||||
kHUD_CB_PATCH_CULL,
|
||||
kHUD_CB_BACK_CULL,
|
||||
kHUD_CB_PATCH_INDIRECT_CULL,
|
||||
kHUD_CB_FREEZE,
|
||||
kHUD_CB_SINGLE_CREASE_PATCH,
|
||||
kHUD_CB_INFINITE_SHARP_PATCH,
|
||||
kHUD_CB_ADAPTIVE,
|
||||
kHUD_CB_DISPLAY_PATCH_COUNTS
|
||||
};
|
||||
|
||||
@implementation OSDView {
|
||||
bool _mouseDown;
|
||||
NSPoint _lastMouse;
|
||||
}
|
||||
|
||||
-(void)mouseDown:(NSEvent *)event {
|
||||
if(event.buttonNumber == 0) {
|
||||
_lastMouse = [event locationInWindow];
|
||||
_mouseDown = !hud.MouseClick(_lastMouse.x, (self.bounds.size.height - _lastMouse.y));
|
||||
}
|
||||
[super mouseDown:event];
|
||||
}
|
||||
|
||||
-(void)mouseUp:(NSEvent *)event {
|
||||
if(event.buttonNumber == 0) {
|
||||
_mouseDown = false;
|
||||
_lastMouse = [event locationInWindow];
|
||||
hud.MouseRelease();
|
||||
}
|
||||
[super mouseUp:event];
|
||||
}
|
||||
|
||||
-(void)mouseDragged:(NSEvent *)event {
|
||||
auto mouse = [NSEvent mouseLocation];
|
||||
hud.MouseMotion(mouse.x, mouse.y);
|
||||
|
||||
if(_mouseDown) {
|
||||
CGPoint delta;
|
||||
delta.x = mouse.x - _lastMouse.x;
|
||||
delta.y = mouse.y - _lastMouse.y;
|
||||
_lastMouse = mouse;
|
||||
|
||||
_controller.osdRenderer.camera->rotationX += delta.x / 2.0;
|
||||
_controller.osdRenderer.camera->rotationY -= delta.y / 2.0;
|
||||
}
|
||||
[super mouseDragged:event];
|
||||
}
|
||||
|
||||
-(void)keyDown:(NSEvent *)event {
|
||||
const auto key = [event.charactersIgnoringModifiers characterAtIndex:0];
|
||||
if(key == '=') {
|
||||
_controller.osdRenderer.tessellationLevel = std::min(_controller.osdRenderer.tessellationLevel + 1, 16.0f);
|
||||
} else if (key == '-') {
|
||||
_controller.osdRenderer.tessellationLevel = std::max(_controller.osdRenderer.tessellationLevel - 1, 0.0f);
|
||||
} else if(!hud.KeyDown(key))
|
||||
[super keyDown:event];
|
||||
}
|
||||
|
||||
-(void)scrollWheel:(NSEvent *)event {
|
||||
_controller.osdRenderer.camera->dollyDistance += event.deltaY / 100.0;
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder {
|
||||
return true;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#define FRAME_HISTORY 30
|
||||
@implementation ViewController {
|
||||
id<MTLDevice> _device;
|
||||
id<MTLCommandQueue> _commandQueue;
|
||||
dispatch_semaphore_t _frameSemaphore;
|
||||
OSDRenderer* _osdRenderer;
|
||||
|
||||
unsigned _currentFrame;
|
||||
double _frameBeginTimestamp[FRAME_HISTORY];
|
||||
|
||||
NSMagnificationGestureRecognizer* _magnificationGesture;
|
||||
|
||||
int _showPatchCounts;
|
||||
}
|
||||
|
||||
-(void)viewDidLoad {
|
||||
|
||||
_device = MTLCreateSystemDefaultDevice();
|
||||
_commandQueue = [_device newCommandQueue];
|
||||
|
||||
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
|
||||
_osdRenderer.displayControlMeshEdges = false;
|
||||
|
||||
_frameSemaphore = dispatch_semaphore_create(3);
|
||||
|
||||
self.view.device = _device;
|
||||
self.view.delegate = self;
|
||||
self.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
|
||||
self.view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
|
||||
self.view.controller = self;
|
||||
self.view.sampleCount = 1;
|
||||
|
||||
self.view->hud.UIScale = 1.0;
|
||||
_osdRenderer.camera->aspectRatio = self.view.bounds.size.width / self.view.bounds.size.height;
|
||||
|
||||
_currentFrame = 0;
|
||||
|
||||
auto renderPipelineDescriptor = [MTLRenderPipelineDescriptor new];
|
||||
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
|
||||
renderPipelineDescriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
|
||||
renderPipelineDescriptor.sampleCount = self.view.sampleCount;
|
||||
|
||||
auto depthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
||||
depthStencilDescriptor.depthWriteEnabled = false;
|
||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||
|
||||
auto& hud = self.view->hud;
|
||||
|
||||
hud.Init(_device, renderPipelineDescriptor, depthStencilDescriptor, self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
|
||||
|
||||
auto callbackCheckbox = [=](bool value, int ID) {
|
||||
switch(ID) {
|
||||
case kHUD_CB_FREEZE:
|
||||
self.osdRenderer.freeze = value;
|
||||
break;
|
||||
case kHUD_CB_VIEW_LOD:
|
||||
self.osdRenderer.useScreenspaceTessellation = value;
|
||||
break;
|
||||
case kHUD_CB_PATCH_CULL:
|
||||
self.osdRenderer.usePatchClipCulling = value;
|
||||
|
||||
break;
|
||||
case kHUD_CB_ANIMATE_VERTICES:
|
||||
self.osdRenderer.animateVertices = value;
|
||||
break;
|
||||
case kHUD_CB_FRACTIONAL_SPACING:
|
||||
self.osdRenderer.useFractionalTessellation = value;
|
||||
break;
|
||||
case kHUD_CB_SINGLE_CREASE_PATCH:
|
||||
self.osdRenderer.useSingleCrease = value;
|
||||
break;
|
||||
case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES:
|
||||
self.osdRenderer.displayControlMeshEdges = value;
|
||||
break;
|
||||
case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS:
|
||||
self.osdRenderer.displayControlMeshVertices = value;
|
||||
break;
|
||||
case kHUD_CB_BACK_CULL:
|
||||
self.osdRenderer.usePatchBackfaceCulling = value;
|
||||
self.osdRenderer.usePrimitiveBackfaceCulling = value;
|
||||
break;
|
||||
case kHUD_CB_PATCH_INDIRECT_CULL:
|
||||
self.osdRenderer.usePatchIndexBuffer = value;
|
||||
break;
|
||||
case kHUD_CB_ADAPTIVE:
|
||||
self.osdRenderer.useAdaptive = value;
|
||||
break;
|
||||
case kHUD_CB_INFINITE_SHARP_PATCH:
|
||||
self.osdRenderer.useInfinitelySharpPatch = value;
|
||||
break;
|
||||
case kHUD_CB_DISPLAY_PATCH_COUNTS:
|
||||
_showPatchCounts = value;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown checkbox ID" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackKernel = [=](int kernelType) {
|
||||
switch((KernelType)kernelType) {
|
||||
case kCPU:
|
||||
case kMetal:
|
||||
self.osdRenderer.kernelType = (KernelType)(kernelType);
|
||||
break;
|
||||
default:
|
||||
assert("Unknown kernelType" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackDisplayStyle = [=](int displayStyle) {
|
||||
switch((DisplayStyle)displayStyle) {
|
||||
case kDisplayStyleWire:
|
||||
case kDisplayStyleShaded:
|
||||
case kDisplayStyleWireOnShaded:
|
||||
self.osdRenderer.displayStyle = (DisplayStyle)displayStyle;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown displayStyle" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackShadingMode = [=](int shadingMode) {
|
||||
switch((ShadingMode)shadingMode) {
|
||||
case kShadingNormal:
|
||||
case kShadingMaterial:
|
||||
case kShadingPatchType:
|
||||
case kShadingPatchCoord:
|
||||
self.osdRenderer.shadingMode = (ShadingMode)shadingMode;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown shadingMode" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackEndCap = [=](int endCap) {
|
||||
switch((EndCap)endCap) {
|
||||
case kEndCapNone:
|
||||
case kEndCapBSplineBasis:
|
||||
case kEndCapGregoryBasis:
|
||||
case kEndCapLegacyGregory:
|
||||
self.osdRenderer.endCapMode = (EndCap)endCap;
|
||||
break;
|
||||
default:
|
||||
assert("Unknown endCap" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackLevel = [=](int level) {
|
||||
self.osdRenderer.refinementLevel = level;
|
||||
};
|
||||
|
||||
auto callbackModel = [=](int modelIndex) {
|
||||
assert(modelIndex >= 0);
|
||||
assert((NSUInteger)modelIndex < self.osdRenderer.loadedModels.count);
|
||||
|
||||
self.osdRenderer.currentModel = self.osdRenderer.loadedModels[modelIndex];
|
||||
};
|
||||
|
||||
int y = 10;
|
||||
hud.AddCheckBox("Control edges (H)",
|
||||
_osdRenderer.displayControlMeshEdges,
|
||||
10, y, callbackCheckbox,
|
||||
kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Control vertices (J)",
|
||||
_osdRenderer.displayControlMeshVertices,
|
||||
10, y, callbackCheckbox,
|
||||
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Animate vertices (M)", _osdRenderer.animateVertices,
|
||||
10, y, callbackCheckbox, kHUD_CB_ANIMATE_VERTICES, 'm');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Screen space LOD (V)", _osdRenderer.useScreenspaceTessellation,
|
||||
10, y, callbackCheckbox, kHUD_CB_VIEW_LOD, 'v');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
|
||||
10, y, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Frustum Patch Culling (B)", _osdRenderer.usePatchClipCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'b');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Backface Culling (L)", _osdRenderer.usePatchBackfaceCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_BACK_CULL, 'l');
|
||||
|
||||
y += 20;
|
||||
hud.AddCheckBox("Patch Index Culling (O)", _osdRenderer.usePatchIndexBuffer,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_INDIRECT_CULL, 'o');
|
||||
|
||||
y += 20;
|
||||
hud.AddCheckBox("Freeze (spc)", _osdRenderer.freeze,
|
||||
10, y, callbackCheckbox, kHUD_CB_FREEZE, ' ');
|
||||
y += 20;
|
||||
|
||||
int displaystyle_pulldown = hud.AddPullDown("DisplayStyle (W)", 200, 10, 250,
|
||||
callbackDisplayStyle, 'w');
|
||||
hud.AddPullDownButton(displaystyle_pulldown, "Wire", kDisplayStyleWire,
|
||||
_osdRenderer.displayStyle == kDisplayStyleWire);
|
||||
hud.AddPullDownButton(displaystyle_pulldown, "Shaded", kDisplayStyleShaded,
|
||||
_osdRenderer.displayStyle == kDisplayStyleShaded);
|
||||
hud.AddPullDownButton(displaystyle_pulldown, "Wire+Shaded", kDisplayStyleWireOnShaded,
|
||||
_osdRenderer.displayStyle == kDisplayStyleWireOnShaded);
|
||||
|
||||
int shading_pulldown = hud.AddPullDown("Shading (C)", 200, 70, 250,
|
||||
callbackShadingMode, 'c');
|
||||
|
||||
hud.AddPullDownButton(shading_pulldown, "Material",
|
||||
kShadingMaterial,
|
||||
_osdRenderer.shadingMode == kShadingMaterial);
|
||||
hud.AddPullDownButton(shading_pulldown, "Patch Type",
|
||||
kShadingPatchType,
|
||||
_osdRenderer.shadingMode == kShadingPatchType);
|
||||
hud.AddPullDownButton(shading_pulldown, "Patch Coord",
|
||||
kShadingPatchCoord,
|
||||
_osdRenderer.shadingMode == kShadingPatchCoord);
|
||||
hud.AddPullDownButton(shading_pulldown, "Normal",
|
||||
kShadingNormal,
|
||||
_osdRenderer.shadingMode == kShadingNormal);
|
||||
|
||||
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
|
||||
hud.AddPullDownButton(compute_pulldown, "CPU", kCPU, _osdRenderer.kernelType == kCPU);
|
||||
hud.AddPullDownButton(compute_pulldown, "Metal", kMetal, _osdRenderer.kernelType == kMetal);
|
||||
{
|
||||
hud.AddCheckBox("Adaptive (`)", _osdRenderer.useAdaptive,
|
||||
10, 190, callbackCheckbox, kHUD_CB_ADAPTIVE, '`');
|
||||
hud.AddCheckBox("Single Crease Patch (S)", _osdRenderer.useSingleCrease,
|
||||
10, 210, callbackCheckbox, kHUD_CB_SINGLE_CREASE_PATCH, 's');
|
||||
hud.AddCheckBox("Inf Sharp Patch (I)", _osdRenderer.useInfinitelySharpPatch,
|
||||
10, 230, callbackCheckbox, kHUD_CB_INFINITE_SHARP_PATCH, 'i');
|
||||
|
||||
int endcap_pulldown = hud.AddPullDown(
|
||||
"End cap (E)", 10, 250, 200, callbackEndCap, 'e');
|
||||
hud.AddPullDownButton(endcap_pulldown,"None",
|
||||
kEndCapNone,
|
||||
_osdRenderer.endCapMode == kEndCapNone);
|
||||
hud.AddPullDownButton(endcap_pulldown, "BSpline",
|
||||
kEndCapBSplineBasis,
|
||||
_osdRenderer.endCapMode == kEndCapBSplineBasis);
|
||||
hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
|
||||
kEndCapGregoryBasis,
|
||||
_osdRenderer.endCapMode == kEndCapGregoryBasis);
|
||||
hud.AddPullDownButton(endcap_pulldown, "LegacyGregory",
|
||||
kEndCapLegacyGregory,
|
||||
_osdRenderer.endCapMode == kEndCapLegacyGregory);
|
||||
}
|
||||
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
char level[16];
|
||||
sprintf(level, "Lv. %d", i);
|
||||
hud.AddRadioButton(3, level, i==2, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
||||
}
|
||||
|
||||
int shapes_pulldown = hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n');
|
||||
for (int i = 0; i < (int)_osdRenderer.loadedModels.count; ++i) {
|
||||
hud.AddPullDownButton(shapes_pulldown, _osdRenderer.loadedModels[i].UTF8String,i);
|
||||
}
|
||||
|
||||
hud.AddCheckBox("Show patch counts (,)", _showPatchCounts, -280, -20, callbackCheckbox, kHUD_CB_DISPLAY_PATCH_COUNTS, ',');
|
||||
|
||||
hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, self.view.drawableSize.width, self.view.drawableSize.height);
|
||||
}
|
||||
|
||||
-(void)drawInMTKView:(MTKView *)view {
|
||||
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
auto commandBuffer = [_commandQueue commandBuffer];
|
||||
|
||||
double avg = 0;
|
||||
for(int i = 0; i < FRAME_HISTORY; i++)
|
||||
avg += _frameBeginTimestamp[i];
|
||||
avg /= FRAME_HISTORY;
|
||||
|
||||
auto renderEncoder = [_osdRenderer drawFrame:commandBuffer];
|
||||
auto& hud = self.view->hud;
|
||||
if(hud.IsVisible()) {
|
||||
if(_showPatchCounts) {
|
||||
int x = -280;
|
||||
int y = -180;
|
||||
hud.DrawString(x, y, "NonPatch : %d",
|
||||
_osdRenderer.patchCounts[Far::PatchDescriptor::QUADS]); y += 20;
|
||||
hud.DrawString(x, y, "Regular : %d",
|
||||
_osdRenderer.patchCounts[Far::PatchDescriptor::REGULAR]); y+= 20;
|
||||
hud.DrawString(x, y, "Gregory : %d",
|
||||
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY]); y+= 20;
|
||||
hud.DrawString(x, y, "Boundary Gregory : %d",
|
||||
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY_BOUNDARY]); y+= 20;
|
||||
hud.DrawString(x, y, "Gregory Basis : %d",
|
||||
_osdRenderer.patchCounts[Far::PatchDescriptor::GREGORY_BASIS]); y+= 20;
|
||||
}
|
||||
|
||||
hud.DrawString(10, -120, "Tess level : %f", _osdRenderer.tessellationLevel);
|
||||
hud.DrawString(10, -20, "FPS = %3.1f", 1.0 / avg);
|
||||
|
||||
|
||||
//Disable Culling & Force Fill mode when drawing the UI
|
||||
[renderEncoder setTriangleFillMode:MTLTriangleFillModeFill];
|
||||
[renderEncoder setCullMode:MTLCullModeNone];
|
||||
self.view->hud.Flush(renderEncoder);
|
||||
}
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
__weak auto blockSemaphore = _frameSemaphore;
|
||||
unsigned frameId = _currentFrame % FRAME_HISTORY;
|
||||
auto frameBeginTime = CACurrentMediaTime();
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
|
||||
dispatch_semaphore_signal(blockSemaphore);
|
||||
_frameBeginTimestamp[frameId] = CACurrentMediaTime() - frameBeginTime;
|
||||
}];
|
||||
|
||||
[commandBuffer presentDrawable:view.currentDrawable];
|
||||
[commandBuffer commit];
|
||||
|
||||
_currentFrame++;
|
||||
}
|
||||
|
||||
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
|
||||
_osdRenderer.camera->aspectRatio = size.width / size.height;
|
||||
self.view->hud.Rebuild(self.view.bounds.size.width, self.view.bounds.size.height, size.width, size.height);
|
||||
}
|
||||
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
|
||||
}
|
||||
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
descriptor.depthAttachmentPixelFormat = self.view.depthStencilPixelFormat;
|
||||
descriptor.colorAttachments[0].pixelFormat = self.view.colorPixelFormat;
|
||||
descriptor.sampleCount = self.view.sampleCount;
|
||||
}
|
||||
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
|
||||
return _commandQueue;
|
||||
}
|
||||
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
|
||||
return _device;
|
||||
}
|
||||
|
||||
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
|
||||
return self.view.currentRenderPassDescriptor;
|
||||
}
|
||||
@end
|
29
examples/mtlViewer/OSX/main.m
Normal file
29
examples/mtlViewer/OSX/main.m
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
33
examples/mtlViewer/iOS/AppDelegate.h
Normal file
33
examples/mtlViewer/iOS/AppDelegate.h
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
61
examples/mtlViewer/iOS/AppDelegate.m
Normal file
61
examples/mtlViewer/iOS/AppDelegate.m
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,73 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
27
examples/mtlViewer/iOS/Base.lproj/LaunchScreen.storyboard
Normal file
27
examples/mtlViewer/iOS/Base.lproj/LaunchScreen.storyboard
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1024" height="1366"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
227
examples/mtlViewer/iOS/Base.lproj/Main.storyboard
Normal file
227
examples/mtlViewer/iOS/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,227 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11147" systemVersion="16A201u" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11119"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="MTKView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1366" height="1024"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Information Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ze8-2s-lED">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oQb-3T-gg6" userLabel="modelPickerView">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="195" id="Qn1-yQ-7c6"/>
|
||||
<constraint firstAttribute="height" constant="102" id="xJP-UH-SIl"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="BYZ-38-t0r" id="jd1-qJ-49i"/>
|
||||
<outlet property="delegate" destination="BYZ-38-t0r" id="OdV-ot-p6a"/>
|
||||
</connections>
|
||||
</pickerView>
|
||||
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minimumValue="1" maximumValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="QQ6-5o-gla">
|
||||
<connections>
|
||||
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="uHZ-dB-XZV"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ref Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N12-GK-yLY">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stepper opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="16" translatesAutoresizingMaskIntoConstraints="NO" id="eYp-5M-Rgk">
|
||||
<connections>
|
||||
<action selector="stepperChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="mBg-38-OPM"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="jQK-WK-vfP">
|
||||
<segments>
|
||||
<segment title="BSpline"/>
|
||||
<segment title="Legacy Gregory"/>
|
||||
<segment title="Gregory Basis"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="endcapChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="vBH-MZ-zYA"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="8kP-4Y-wzA">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="UsH-Nw-M31"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Wireframe" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FvR-NK-6s0" userLabel="Wireframe">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backpatch Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="esT-7h-XLG">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="P8z-O2-OLV">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="w7T-KH-L3E"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="5Ns-3P-r13">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ym1-Xw-wU6"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="fw1-9C-P6U">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="8kp-Rh-Yua"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Backface Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iw4-VH-Zwm">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Patch Clip Culling" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5xP-bY-PgM">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Crease" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kuw-3r-nzl">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7yA-a6-Sq7">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="Yg5-z5-avS"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Control Mesh" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cRi-2K-jkK">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Screenspace Tessellation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ioY-T2-PEM">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tes Lvl." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlx-hC-oDg">
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sDC-ZC-b6I">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="ebT-0s-gYR"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Ta2-7B-7Ck">
|
||||
<connections>
|
||||
<action selector="switchChanged:" destination="BYZ-38-t0r" eventType="valueChanged" id="PcJ-3J-UKL"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-iT-gpT">
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="57" id="8qk-aN-q1z"/>
|
||||
<constraint firstAttribute="width" constant="194" id="aSF-hS-BWT"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="BYZ-38-t0r" id="4w5-fv-wIj"/>
|
||||
<outlet property="delegate" destination="BYZ-38-t0r" id="73C-8g-Biy"/>
|
||||
</connections>
|
||||
</pickerView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="leading" secondItem="esT-7h-XLG" secondAttribute="trailing" constant="8" id="0zt-WU-LC3"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="2nS-t9-ncz"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="404-z0-Fv7"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="leading" secondItem="FvR-NK-6s0" secondAttribute="trailing" constant="8" id="5rd-n5-Uxl"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="oQb-3T-gg6" secondAttribute="bottom" constant="20" id="6dr-og-11f"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="AnK-qT-Bca"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="leading" secondItem="dlx-hC-oDg" secondAttribute="trailing" constant="8" id="B0o-kO-368"/>
|
||||
<constraint firstItem="QQ6-5o-gla" firstAttribute="leading" secondItem="N12-GK-yLY" secondAttribute="trailing" constant="8" id="DrB-sY-inQ"/>
|
||||
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="top" secondItem="sDC-ZC-b6I" secondAttribute="bottom" constant="8" id="EK0-Q5-QyW"/>
|
||||
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="leading" secondItem="cRi-2K-jkK" secondAttribute="trailing" constant="8" id="En4-Ve-B3K"/>
|
||||
<constraint firstItem="8Ky-iT-gpT" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="HnT-dY-hLh"/>
|
||||
<constraint firstItem="oQb-3T-gg6" firstAttribute="leading" secondItem="fw1-9C-P6U" secondAttribute="trailing" constant="24" id="JmG-em-jfy"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="top" secondItem="Ta2-7B-7Ck" secondAttribute="bottom" constant="8" id="O1O-AY-rOc"/>
|
||||
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="centerY" secondItem="cRi-2K-jkK" secondAttribute="centerY" id="OGy-au-4ty"/>
|
||||
<constraint firstItem="sDC-ZC-b6I" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="OLn-EQ-Ol5"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="centerY" secondItem="esT-7h-XLG" secondAttribute="centerY" id="Oxf-2f-wTD"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="top" secondItem="QQ6-5o-gla" secondAttribute="bottom" constant="4" id="PJS-Lq-bIL"/>
|
||||
<constraint firstItem="Ta2-7B-7Ck" firstAttribute="trailing" secondItem="jQK-WK-vfP" secondAttribute="trailing" id="PVt-1f-oef"/>
|
||||
<constraint firstItem="Ze8-2s-lED" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" constant="20" id="SZK-UA-BiA"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="fw1-9C-P6U" secondAttribute="bottom" constant="20" id="Uw7-fz-We7"/>
|
||||
<constraint firstItem="sDC-ZC-b6I" firstAttribute="leading" secondItem="kuw-3r-nzl" secondAttribute="trailing" constant="8" id="W06-wv-gqs"/>
|
||||
<constraint firstItem="oQb-3T-gg6" firstAttribute="top" secondItem="8Ky-iT-gpT" secondAttribute="bottom" constant="8" id="b0I-kW-GRc"/>
|
||||
<constraint firstItem="QQ6-5o-gla" firstAttribute="centerY" secondItem="N12-GK-yLY" secondAttribute="centerY" id="bqu-uw-PqG"/>
|
||||
<constraint firstItem="eYp-5M-Rgk" firstAttribute="centerY" secondItem="dlx-hC-oDg" secondAttribute="centerY" id="cV6-GZ-8IP"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="leading" secondItem="ioY-T2-PEM" secondAttribute="trailing" constant="8" id="cqL-gl-vn2"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="leading" secondItem="5xP-bY-PgM" secondAttribute="trailing" constant="8" id="dhX-z5-kgA"/>
|
||||
<constraint firstItem="jQK-WK-vfP" firstAttribute="top" secondItem="7yA-a6-Sq7" secondAttribute="bottom" constant="8" id="egb-qP-Lva"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="centerY" secondItem="Iw4-VH-Zwm" secondAttribute="centerY" id="fEO-gM-cmZ"/>
|
||||
<constraint firstItem="QQ6-5o-gla" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="ggj-9I-tbQ"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="gqA-q9-SK3"/>
|
||||
<constraint firstItem="Ze8-2s-lED" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="20" id="kTX-YC-JKR"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="jQK-WK-vfP" secondAttribute="bottom" constant="20" id="kuT-qk-ibg"/>
|
||||
<constraint firstItem="8kP-4Y-wzA" firstAttribute="centerY" secondItem="FvR-NK-6s0" secondAttribute="centerY" id="n3L-qM-7Pr"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="centerY" secondItem="5xP-bY-PgM" secondAttribute="centerY" id="nP1-Bt-GuV"/>
|
||||
<constraint firstItem="oQb-3T-gg6" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="pIi-zk-crx"/>
|
||||
<constraint firstItem="5xP-bY-PgM" firstAttribute="leading" secondItem="jQK-WK-vfP" secondAttribute="trailing" constant="20" id="pvx-Go-b8B"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="top" secondItem="P8z-O2-OLV" secondAttribute="bottom" constant="8" id="pwK-2F-IIf"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="top" secondItem="8kP-4Y-wzA" secondAttribute="bottom" constant="8" id="q11-mD-QDz"/>
|
||||
<constraint firstItem="oQb-3T-gg6" firstAttribute="top" secondItem="eYp-5M-Rgk" secondAttribute="bottom" constant="8" id="qfG-FK-QD4"/>
|
||||
<constraint firstItem="P8z-O2-OLV" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="rha-qA-vsj"/>
|
||||
<constraint firstItem="8Ky-iT-gpT" firstAttribute="top" secondItem="eYp-5M-Rgk" secondAttribute="bottom" constant="8" id="rjU-ER-xAm"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="trailing" secondItem="8kP-4Y-wzA" secondAttribute="trailing" id="ro3-hx-iLk"/>
|
||||
<constraint firstItem="5Ns-3P-r13" firstAttribute="leading" secondItem="Iw4-VH-Zwm" secondAttribute="trailing" constant="8" id="ry7-bQ-bRa"/>
|
||||
<constraint firstItem="fw1-9C-P6U" firstAttribute="top" secondItem="5Ns-3P-r13" secondAttribute="bottom" constant="8" id="tsW-3r-293"/>
|
||||
<constraint firstItem="7yA-a6-Sq7" firstAttribute="centerY" secondItem="ioY-T2-PEM" secondAttribute="centerY" id="wE0-Cg-4Qf"/>
|
||||
<constraint firstItem="sDC-ZC-b6I" firstAttribute="centerY" secondItem="kuw-3r-nzl" secondAttribute="centerY" id="wTg-7H-KXF"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="qfG-FK-QD4"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="backfaceCullingSwitch" destination="5Ns-3P-r13" id="n8X-2V-BRl"/>
|
||||
<outlet property="backpatchCullingSwitch" destination="P8z-O2-OLV" id="VIe-Lv-hsC"/>
|
||||
<outlet property="controlMeshSwitch" destination="Ta2-7B-7Ck" id="hVP-58-sGA"/>
|
||||
<outlet property="endcapSegmentedControl" destination="jQK-WK-vfP" id="MIt-kE-Kwg"/>
|
||||
<outlet property="frameTimeLabel" destination="Ze8-2s-lED" id="vLj-Id-oiv"/>
|
||||
<outlet property="modelPickerView" destination="oQb-3T-gg6" id="YLl-SI-Azc"/>
|
||||
<outlet property="patchClipCullingSwitch" destination="fw1-9C-P6U" id="P2G-3F-eJh"/>
|
||||
<outlet property="refLvlLabel" destination="N12-GK-yLY" id="lXc-6r-pZY"/>
|
||||
<outlet property="refinementStepper" destination="QQ6-5o-gla" id="URK-fS-krY"/>
|
||||
<outlet property="screenspaceTessellationSwitch" destination="7yA-a6-Sq7" id="RpM-ER-4Oy"/>
|
||||
<outlet property="shadingModePickerView" destination="8Ky-iT-gpT" id="PAS-0I-Vju"/>
|
||||
<outlet property="singleCreaseSwitch" destination="sDC-ZC-b6I" id="Arw-OY-Z4A"/>
|
||||
<outlet property="tesLvLlabel" destination="dlx-hC-oDg" id="haB-Hi-A9B"/>
|
||||
<outlet property="tessellationStepper" destination="eYp-5M-Rgk" id="IFG-H5-rJS"/>
|
||||
<outlet property="wireframeSwitch" destination="8kP-4Y-wzA" id="y3a-yu-4cs"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="476.57393850658855" y="533.7890625"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<color key="tintColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
</document>
|
50
examples/mtlViewer/iOS/Info.plist
Normal file
50
examples/mtlViewer/iOS/Info.plist
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>mtlViewer</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.osd.mtlViewer</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>mtlViewer</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>metal</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
33
examples/mtlViewer/iOS/ViewController.h
Normal file
33
examples/mtlViewer/iOS/ViewController.h
Normal file
@ -0,0 +1,33 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "../mtlViewer.h"
|
||||
|
||||
@interface ViewController : UIViewController<
|
||||
MTKViewDelegate,
|
||||
UIPickerViewDelegate,
|
||||
UIPickerViewDataSource,
|
||||
OSDRendererDelegate
|
||||
>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UILabel *refLvlLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *tesLvLlabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *frameTimeLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIPickerView *modelPickerView;
|
||||
@property (weak, nonatomic) IBOutlet UIPickerView *shadingModePickerView;
|
||||
@property (weak, nonatomic) IBOutlet UIStepper *tessellationStepper;
|
||||
@property (weak, nonatomic) IBOutlet UIStepper *refinementStepper;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *wireframeSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *backpatchCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *backfaceCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *patchClipCullingSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *singleCreaseSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *controlMeshSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *screenspaceTessellationSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISegmentedControl *endcapSegmentedControl;
|
||||
- (IBAction)stepperChanged:(UIStepper *)sender;
|
||||
- (IBAction)switchChanged:(UISwitch *)sender;
|
||||
- (IBAction)endcapChanged:(UISegmentedControl *)sender;
|
||||
|
||||
|
||||
@end
|
||||
|
249
examples/mtlViewer/iOS/ViewController.mm
Normal file
249
examples/mtlViewer/iOS/ViewController.mm
Normal file
@ -0,0 +1,249 @@
|
||||
#import "ViewController.h"
|
||||
|
||||
#define FRAME_HISTORY 30
|
||||
@interface ViewController ()
|
||||
{
|
||||
dispatch_semaphore_t _frameSemaphore;
|
||||
CGPoint _startTouch;
|
||||
bool _isTouching;
|
||||
OSDRenderer* _osdRenderer;
|
||||
MTKView* _view;
|
||||
id<MTLDevice> _device;
|
||||
id<MTLCommandQueue> _commandQueue;
|
||||
|
||||
double _frameTimes[FRAME_HISTORY];
|
||||
uint64_t _currentFrame;
|
||||
|
||||
UIPanGestureRecognizer *_zoomGesture;
|
||||
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
|
||||
_osdRenderer.camera->aspectRatio = size.width / size.height;
|
||||
}
|
||||
|
||||
-(void)drawInMTKView:(MTKView *)view {
|
||||
dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER);
|
||||
auto commandBuffer = [_commandQueue commandBuffer];
|
||||
[[_osdRenderer drawFrame:commandBuffer] endEncoding];
|
||||
|
||||
__weak auto blockSemaphore = _frameSemaphore;
|
||||
unsigned frameIndex = _currentFrame % FRAME_HISTORY;
|
||||
const auto beginTime = CACurrentMediaTime();
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull c) {
|
||||
dispatch_semaphore_signal(blockSemaphore);
|
||||
_frameTimes[frameIndex] = CACurrentMediaTime() - beginTime;
|
||||
}];
|
||||
[commandBuffer presentDrawable:_view.currentDrawable];
|
||||
[commandBuffer commit];
|
||||
_currentFrame++;
|
||||
|
||||
double frameAverage = 0;
|
||||
for(auto& x : _frameTimes)
|
||||
frameAverage += x;
|
||||
|
||||
frameAverage /= 30.0;
|
||||
|
||||
_frameTimeLabel.text = [NSString stringWithFormat:@"%0.2f ms", frameAverage * 1000.0];
|
||||
}
|
||||
|
||||
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||
return UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
_view = (MTKView*)self.view;
|
||||
_frameSemaphore = dispatch_semaphore_create(3);
|
||||
|
||||
_device = MTLCreateSystemDefaultDevice();
|
||||
_commandQueue = [_device newCommandQueue];
|
||||
|
||||
_view.device = _device;
|
||||
_view.depthStencilPixelFormat = MTLPixelFormatDepth32Float;
|
||||
_view.sampleCount = 2;
|
||||
_view.frame = CGRectMake(0, 0, 1920, 1080);
|
||||
_view.contentScaleFactor = 1;
|
||||
_view.clearColor = MTLClearColorMake(0.4245, 0.4167, 0.4245, 1);
|
||||
|
||||
_osdRenderer = [[OSDRenderer alloc] initWithDelegate:self];
|
||||
|
||||
_view.delegate = self;
|
||||
|
||||
_zoomGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_zoomView)];
|
||||
_zoomGesture.minimumNumberOfTouches = 2;
|
||||
_zoomGesture.maximumNumberOfTouches = 2;
|
||||
_zoomGesture.cancelsTouchesInView = true;
|
||||
|
||||
[_view addGestureRecognizer:_zoomGesture];
|
||||
|
||||
|
||||
[self _applyOptions];
|
||||
}
|
||||
|
||||
-(void)_applyOptions {
|
||||
_osdRenderer.useSingleCrease = _singleCreaseSwitch.isOn;
|
||||
_osdRenderer.usePatchBackfaceCulling = _backpatchCullingSwitch.isOn;
|
||||
_osdRenderer.usePrimitiveBackfaceCulling = _backfaceCullingSwitch.isOn;
|
||||
_osdRenderer.useScreenspaceTessellation = _screenspaceTessellationSwitch.isOn;
|
||||
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
|
||||
_osdRenderer.displayControlMeshVertices = _controlMeshSwitch.isOn;
|
||||
_osdRenderer.displayControlMeshEdges = _controlMeshSwitch.isOn;
|
||||
_osdRenderer.usePatchClipCulling = _patchClipCullingSwitch.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
_osdRenderer.useAdaptive = true;
|
||||
_osdRenderer.freeze = true;
|
||||
_osdRenderer.animateVertices = false;
|
||||
_osdRenderer.kernelType = kMetal;
|
||||
_osdRenderer.refinementLevel = _refinementStepper.value;
|
||||
_osdRenderer.tessellationLevel = _tessellationStepper.value;
|
||||
_osdRenderer.endCapMode = (EndCap)(1 + _endcapSegmentedControl.selectedSegmentIndex);
|
||||
|
||||
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
|
||||
[_tesLvLlabel sizeToFit];
|
||||
|
||||
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
|
||||
[_refLvlLabel sizeToFit];
|
||||
}
|
||||
|
||||
-(void)_zoomView {
|
||||
static float lastY = 0;
|
||||
if(_zoomGesture.state == UIGestureRecognizerStateBegan) {
|
||||
lastY = [_zoomGesture translationInView:_view].y;
|
||||
} else if(_zoomGesture.state == UIGestureRecognizerStateChanged) {
|
||||
const auto currentY = [_zoomGesture translationInView:_view].y;
|
||||
const auto deltaY = (currentY - lastY) / 100.0;
|
||||
lastY = currentY;
|
||||
_osdRenderer.camera->dollyDistance += deltaY;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
_isTouching = true;
|
||||
_startTouch = [touches.anyObject locationInView:self.view];
|
||||
[super touchesBegan:touches withEvent:event];
|
||||
}
|
||||
|
||||
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
_isTouching = false;
|
||||
[super touchesEnded:touches withEvent:event];
|
||||
}
|
||||
|
||||
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
if(_isTouching)
|
||||
{
|
||||
for(UITouch* touch in touches)
|
||||
{
|
||||
CGPoint location = [touch locationInView:self.view];
|
||||
_startTouch = [touch previousLocationInView:self.view];
|
||||
|
||||
double deltaX = location.x - _startTouch.x;
|
||||
double deltaY = location.y - _startTouch.y;
|
||||
|
||||
_osdRenderer.camera->rotationX += deltaX / 5.0;
|
||||
_osdRenderer.camera->rotationY += deltaY / 5.0;
|
||||
}
|
||||
}
|
||||
[super touchesMoved:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer *)renderer {
|
||||
return _device;
|
||||
}
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer *)renderer {
|
||||
return _commandQueue;
|
||||
}
|
||||
-(MTLRenderPassDescriptor *)renderPassDescriptorFor:(OSDRenderer *)renderer {
|
||||
return _view.currentRenderPassDescriptor;
|
||||
}
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
|
||||
}
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor *)descriptor for:(OSDRenderer *)renderer {
|
||||
descriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
|
||||
descriptor.depthAttachmentPixelFormat = _view.depthStencilPixelFormat;
|
||||
descriptor.sampleCount = _view.sampleCount;
|
||||
}
|
||||
- (IBAction)stepperChanged:(UIStepper *)sender {
|
||||
if(sender == _tessellationStepper) {
|
||||
_osdRenderer.tessellationLevel = sender.value;
|
||||
_tesLvLlabel.text = [NSString stringWithFormat:@"Tes Lvl. %d", (int)_osdRenderer.tessellationLevel];
|
||||
[_tesLvLlabel sizeToFit];
|
||||
|
||||
} else if (sender == _refinementStepper) {
|
||||
_osdRenderer.refinementLevel = sender.value;
|
||||
_refLvlLabel.text = [NSString stringWithFormat:@"Ref Lvl. %d", _osdRenderer.refinementLevel];
|
||||
[_refLvlLabel sizeToFit];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)switchChanged:(UISwitch *)sender {
|
||||
if(sender == _wireframeSwitch) {
|
||||
_osdRenderer.displayStyle = _wireframeSwitch.isOn ? kDisplayStyleWireOnShaded : kDisplayStyleShaded;
|
||||
} else if(sender == _backpatchCullingSwitch) {
|
||||
_osdRenderer.usePatchBackfaceCulling = sender.isOn;
|
||||
} else if(sender == _backfaceCullingSwitch) {
|
||||
_osdRenderer.usePrimitiveBackfaceCulling = sender.isOn;
|
||||
} else if(sender == _patchClipCullingSwitch) {
|
||||
_osdRenderer.usePatchClipCulling = sender.isOn;
|
||||
} else if(sender == _singleCreaseSwitch) {
|
||||
_osdRenderer.useSingleCrease = sender.isOn;
|
||||
} else if(sender == _controlMeshSwitch) {
|
||||
_osdRenderer.displayControlMeshEdges = sender.isOn;
|
||||
_osdRenderer.displayControlMeshVertices = sender.isOn;
|
||||
} else if(sender == _screenspaceTessellationSwitch) {
|
||||
_osdRenderer.useScreenspaceTessellation = sender.isOn;
|
||||
_osdRenderer.useFractionalTessellation = _osdRenderer.useScreenspaceTessellation;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)endcapChanged:(UISegmentedControl *)sender {
|
||||
_osdRenderer.endCapMode = (EndCap)(1 + sender.selectedSegmentIndex);
|
||||
}
|
||||
|
||||
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
|
||||
if(pickerView == _modelPickerView) {
|
||||
return _osdRenderer.loadedModels.count;
|
||||
} else if(pickerView == _shadingModePickerView) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
|
||||
if(pickerView == _modelPickerView) {
|
||||
return _osdRenderer.loadedModels[row];
|
||||
} else if(pickerView == _shadingModePickerView) {
|
||||
switch((ShadingMode)row) {
|
||||
case kShadingMaterial: return @"Material";
|
||||
case kShadingNormal: return @"Normal";
|
||||
case kShadingPatchCoord: return @"Patch Coord";
|
||||
case kShadingPatchType: return @"Patch Type";
|
||||
}
|
||||
}
|
||||
return @"";
|
||||
}
|
||||
|
||||
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
||||
if(pickerView == _modelPickerView) {
|
||||
_osdRenderer.currentModel = _osdRenderer.loadedModels[row];
|
||||
} else if(pickerView == _shadingModePickerView) {
|
||||
_osdRenderer.shadingMode = (ShadingMode)row;
|
||||
}
|
||||
}
|
||||
@end
|
8
examples/mtlViewer/iOS/main.m
Normal file
8
examples/mtlViewer/iOS/main.m
Normal file
@ -0,0 +1,8 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
122
examples/mtlViewer/init_shapes.h
Normal file
122
examples/mtlViewer/init_shapes.h
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../../regression/common/shape_utils.h"
|
||||
#include "../../regression/shapes/all.h"
|
||||
|
||||
struct ShapeDesc {
|
||||
|
||||
ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme,
|
||||
bool iIsLeftHanded = false) :
|
||||
name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { }
|
||||
|
||||
std::string name,
|
||||
data;
|
||||
Scheme scheme;
|
||||
bool isLeftHanded;
|
||||
};
|
||||
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test8", catmark_gregory_test8, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/ ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pole8", catmark_pole8, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pole64", catmark_pole64, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark ) );
|
||||
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) );
|
||||
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) );
|
||||
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) );
|
||||
// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) );
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) );
|
||||
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole360", loop_pole360, kLoop ) );
|
||||
}
|
110
examples/mtlViewer/mtlViewer.h
Normal file
110
examples/mtlViewer/mtlViewer.h
Normal file
@ -0,0 +1,110 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
typedef enum {
|
||||
kEndCapNone = 0,
|
||||
kEndCapBSplineBasis,
|
||||
kEndCapLegacyGregory,
|
||||
kEndCapGregoryBasis,
|
||||
} EndCap;
|
||||
|
||||
typedef enum {
|
||||
kCPU = 0,
|
||||
kMetal,
|
||||
} KernelType;
|
||||
|
||||
typedef enum {
|
||||
kDisplayStyleWire = 0,
|
||||
kDisplayStyleShaded,
|
||||
kDisplayStyleWireOnShaded,
|
||||
} DisplayStyle;
|
||||
|
||||
typedef enum {
|
||||
kShadingMaterial = 0,
|
||||
kShadingPatchType,
|
||||
kShadingNormal,
|
||||
kShadingPatchCoord
|
||||
} ShadingMode;
|
||||
|
||||
|
||||
typedef struct {
|
||||
float rotationX;
|
||||
float rotationY;
|
||||
float dollyDistance;
|
||||
float aspectRatio;
|
||||
} Camera;
|
||||
|
||||
@class OSDRenderer;
|
||||
|
||||
@protocol OSDRendererDelegate <NSObject>
|
||||
-(id<MTLDevice>)deviceFor:(OSDRenderer*)renderer;
|
||||
-(id<MTLCommandQueue>)commandQueueFor:(OSDRenderer*)renderer;
|
||||
-(MTLRenderPassDescriptor*)renderPassDescriptorFor:(OSDRenderer*)renderer;
|
||||
-(void)setupDepthStencilState:(MTLDepthStencilDescriptor*)descriptor for:(OSDRenderer*)renderer;
|
||||
-(void)setupRenderPipelineState:(MTLRenderPipelineDescriptor*)descriptor for:(OSDRenderer*)renderer;
|
||||
@end
|
||||
|
||||
@interface OSDRenderer : NSObject
|
||||
|
||||
-(instancetype)initWithDelegate:(id<OSDRendererDelegate>)delegate;
|
||||
|
||||
-(id<MTLRenderCommandEncoder>)drawFrame:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
@property (readonly, nonatomic) id<OSDRendererDelegate> delegate;
|
||||
|
||||
@property (nonatomic) unsigned refinementLevel;
|
||||
@property (nonatomic) float tessellationLevel;
|
||||
|
||||
@property (readonly, nonatomic) NSArray<NSString*>* loadedModels;
|
||||
@property (nonatomic) NSString* currentModel;
|
||||
|
||||
@property (readonly, nonatomic) Camera* camera;
|
||||
|
||||
@property (readonly, nonatomic) int* patchCounts;
|
||||
|
||||
@property (nonatomic) bool useFractionalTessellation;
|
||||
@property (nonatomic) bool useScreenspaceTessellation;
|
||||
@property (nonatomic) bool usePatchIndexBuffer;
|
||||
@property (nonatomic) bool usePatchBackfaceCulling;
|
||||
@property (nonatomic) bool usePatchClipCulling;
|
||||
@property (nonatomic) bool useSingleCrease;
|
||||
@property (nonatomic) bool useInfinitelySharpPatch;
|
||||
@property (nonatomic) bool useStageIn;
|
||||
@property (nonatomic) bool usePrimitiveBackfaceCulling;
|
||||
@property (nonatomic) bool useAdaptive;
|
||||
@property (nonatomic) bool freeze;
|
||||
@property (nonatomic) bool animateVertices;
|
||||
@property (nonatomic) bool displayControlMeshEdges;
|
||||
@property (nonatomic) bool displayControlMeshVertices;
|
||||
@property (nonatomic) DisplayStyle displayStyle;
|
||||
@property (nonatomic) ShadingMode shadingMode;
|
||||
@property (nonatomic) EndCap endCapMode;
|
||||
@property (nonatomic) KernelType kernelType;
|
||||
|
||||
@end
|
685
examples/mtlViewer/mtlViewer.metal
Normal file
685
examples/mtlViewer/mtlViewer.metal
Normal file
@ -0,0 +1,685 @@
|
||||
#line 0 "examples/mtlViewer/mtlViewer.metal"
|
||||
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
#define SHADING_TYPE_MATERIAL 0
|
||||
#define SHADING_TYPE_PATCH 1
|
||||
#define SHADING_TYPE_NORMAL 2
|
||||
#define SHADING_TYPE_PATCH_COORD 3
|
||||
|
||||
|
||||
struct PerFrameConstants {
|
||||
float4x4 ModelViewMatrix;
|
||||
float4x4 ProjectionMatrix;
|
||||
float4x4 ModelViewProjectionMatrix;
|
||||
float4x4 ModelViewInverseMatrix;
|
||||
float TessLevel;
|
||||
};
|
||||
|
||||
struct OutputVertex {
|
||||
float4 positionOut [[position]];
|
||||
float3 position;
|
||||
float3 normal;
|
||||
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
float3 patchColor;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SolidColorVertex {
|
||||
float4 positionOut [[position]];
|
||||
|
||||
half4 getColor() const {
|
||||
return unpack_unorm4x8_to_half(_color);
|
||||
}
|
||||
|
||||
void setColor(half4 color) {
|
||||
_color = pack_half_to_unorm4x8(color);
|
||||
}
|
||||
|
||||
private:
|
||||
uint _color [[flat, user(color)]];
|
||||
};
|
||||
struct PackedInputVertex {
|
||||
packed_float3 position;
|
||||
};
|
||||
|
||||
struct Light {
|
||||
float3 Position;
|
||||
float3 ambient;
|
||||
float3 diffuse;
|
||||
float3 specular;
|
||||
};
|
||||
|
||||
float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eyePos, float3 eyeN)
|
||||
{
|
||||
|
||||
float3 color(0);
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
const auto l = lightData[i].Position;
|
||||
const auto h = normalize(l + float3(0,0,1));
|
||||
const auto d = max(0.0, dot(eyeN, l));
|
||||
const auto s = powr(max(0.0, dot(eyeN, h)), 500.0f);
|
||||
|
||||
color += lightData[i].ambient
|
||||
+ d * lightData[i].diffuse * diffuseColor
|
||||
+ s * lightData[i].specular;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
const constant float4 patchColors[] = {
|
||||
float4(1.0f, 1.0f, 1.0f, 1.0f), // regular
|
||||
float4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
|
||||
float4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
|
||||
float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
|
||||
float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
|
||||
float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
|
||||
|
||||
float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
|
||||
float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
|
||||
float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
|
||||
float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
|
||||
float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
|
||||
float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
|
||||
|
||||
float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
|
||||
float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
|
||||
float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
|
||||
float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
|
||||
float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
|
||||
float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
|
||||
|
||||
float4(0.0f, 1.0f, 0.0f, 1.0f), // corner
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
|
||||
float4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
|
||||
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
|
||||
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
|
||||
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
|
||||
float4(1.0f, 0.7f, 0.3f, 1.0f) // gregory basis
|
||||
};
|
||||
|
||||
float4
|
||||
getAdaptivePatchColor(int3 patchParam
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
, float2 vSegments
|
||||
#else
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
int patchType = 0;
|
||||
|
||||
int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam));
|
||||
if (edgeCount == 1) {
|
||||
patchType = 2; // BOUNDARY
|
||||
}
|
||||
if (edgeCount == 2) {
|
||||
patchType = 3; // CORNER
|
||||
}
|
||||
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
}
|
||||
#elif OSD_PATCH_GREGORY
|
||||
patchType = 4;
|
||||
#elif OSD_PATCH_GREGORY_BOUNDARY
|
||||
patchType = 5;
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
patchType = 6;
|
||||
#endif
|
||||
|
||||
int pattern = popcount(OsdGetPatchTransitionMask(patchParam));
|
||||
|
||||
return patchColors[6*patchType + pattern];
|
||||
}
|
||||
|
||||
#if OSD_IS_ADAPTIVE
|
||||
#if USE_STAGE_IN
|
||||
#if OSD_PATCH_REGULAR
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float3 P1 [[attribute(1)]];
|
||||
float3 P2 [[attribute(2)]];
|
||||
#if !USE_PTVS_SHARPNESS
|
||||
float2 vSegments [[attribute(3)]];
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo [[attribute(5)]];
|
||||
float4 tessOuterHi [[attribute(6)]];
|
||||
#endif
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
float3 Ep [[attribute(1)]];
|
||||
float3 Em [[attribute(2)]];
|
||||
float3 Fp [[attribute(3)]];
|
||||
float3 Fm [[attribute(4)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#elif OSD_PATCH_GREGORY_BASIS
|
||||
struct ControlPoint
|
||||
{
|
||||
float3 position [[attribute(0)]];
|
||||
};
|
||||
|
||||
struct PatchInput
|
||||
{
|
||||
patch_control_point<ControlPoint> cv;
|
||||
int3 patchParam [[attribute(10)]];
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Kernel
|
||||
//----------------------------------------------------------
|
||||
//The user of OSD should define this kernel which serves as the landing point for all patch computation
|
||||
//This compute function should just be copied and pasted, modifying the section under "User Vertex Transform"
|
||||
//Or the entire function may be moddified as needed (for example to add a patch index buffer)
|
||||
kernel void compute_main(
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
unsigned thread_position_in_grid [[thread_position_in_grid]],
|
||||
unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]],
|
||||
unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]],
|
||||
OsdPatchParamBufferSet osdBuffers, //This struct contains all of the buffers needed by OSD
|
||||
device MTLQuadTessellationFactorsHalf* quadTessellationFactors [[buffer(QUAD_TESSFACTORS_INDEX)]]
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
,device unsigned* patchIndex [[buffer(OSD_PATCH_INDEX_BUFFER_INDEX)]]
|
||||
,device MTLDrawPatchIndirectArguments* drawIndirectCommands [[buffer(OSD_DRAWINDIRECT_BUFFER_INDEX)]]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Kernel Setup
|
||||
//----------------------------------------------------------
|
||||
|
||||
//Contains the shared patchParam value used by all threads that act upon a single patch
|
||||
//the .z (sharpness) field is set to -1 (NAN) if that patch should be culled to signal other threads to return.
|
||||
threadgroup int3 patchParam[PATCHES_PER_THREADGROUP];
|
||||
|
||||
threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH];
|
||||
|
||||
const auto real_threadgroup = thread_position_in_grid / REAL_THREADGROUP_DIVISOR;
|
||||
const auto subthreadgroup_in_threadgroup = thread_position_in_threadgroup / REAL_THREADGROUP_DIVISOR;
|
||||
const auto real_thread_in_threadgroup = thread_position_in_threadgroup & (REAL_THREADGROUP_DIVISOR - 1);
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
const auto validThread = thread_position_in_grid * CONTROL_POINTS_PER_THREAD < osdBuffers.kernelExecutionLimit;
|
||||
#else
|
||||
const auto validThread = true;
|
||||
if(thread_position_in_grid * CONTROL_POINTS_PER_THREAD >= osdBuffers.kernelExecutionLimit)
|
||||
return;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Vertex Transform
|
||||
//----------------------------------------------------------
|
||||
if(validThread)
|
||||
{
|
||||
patchParam[subthreadgroup_in_threadgroup] = OsdGetPatchParam(real_threadgroup, osdBuffers.patchParamBuffer);
|
||||
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
{
|
||||
const auto vertexId = osdBuffers.indexBuffer[(thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset) * IndexLookupStride];
|
||||
const auto v = osdBuffers.vertexBuffer[vertexId];
|
||||
|
||||
threadgroup auto& patchVertex = patchVertices[thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset];
|
||||
|
||||
//----------------------------------------------------------
|
||||
// User Vertex Transform
|
||||
//----------------------------------------------------------
|
||||
|
||||
OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Patch Cull
|
||||
//----------------------------------------------------------
|
||||
if(validThread)
|
||||
{
|
||||
#if PATCHES_PER_THREADGROUP > 1
|
||||
auto patch = patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_THREAD * CONTROL_POINTS_PER_PATCH;
|
||||
#else
|
||||
//Small optimization for the '1 patch per threadgroup' case
|
||||
auto patch = patchVertices;
|
||||
#endif
|
||||
|
||||
if(!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix))
|
||||
{
|
||||
#if !OSD_USE_PATCH_INDEX_BUFFER
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[1] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[2] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].edgeTessellationFactor[3] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[0] = 0.0h;
|
||||
quadTessellationFactors[real_threadgroup].insideTessellationFactor[1] = 0.0h;
|
||||
#endif
|
||||
|
||||
patchParam[subthreadgroup_in_threadgroup].z = -1;
|
||||
#if !NEEDS_BARRIER
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Patch Compute
|
||||
//----------------------------------------------------------
|
||||
if(validThread && patchParam[subthreadgroup_in_threadgroup].z != -1)
|
||||
{
|
||||
for(unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; threadOffset++)
|
||||
{
|
||||
OsdComputePerPatchVertex(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
real_thread_in_threadgroup * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
real_threadgroup,
|
||||
thread_position_in_grid * CONTROL_POINTS_PER_THREAD + threadOffset,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#if NEEDS_BARRIER
|
||||
threadgroup_barrier(mem_flags::mem_device_and_threadgroup);
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// OSD Tessellation Factors
|
||||
//----------------------------------------------------------
|
||||
if(validThread && real_thread_in_threadgroup == 0)
|
||||
{
|
||||
|
||||
#if OSD_USE_PATCH_INDEX_BUFFER
|
||||
const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed);
|
||||
patchIndex[patchId] = real_threadgroup;
|
||||
#else
|
||||
const auto patchId = real_threadgroup;
|
||||
#endif
|
||||
|
||||
OsdComputePerPatchFactors(
|
||||
patchParam[subthreadgroup_in_threadgroup],
|
||||
frameConsts.TessLevel,
|
||||
real_threadgroup,
|
||||
frameConsts.ProjectionMatrix,
|
||||
frameConsts.ModelViewMatrix,
|
||||
osdBuffers,
|
||||
patchVertices + subthreadgroup_in_threadgroup * CONTROL_POINTS_PER_PATCH,
|
||||
quadTessellationFactors[patchId]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]]
|
||||
vertex OutputVertex vertex_main(
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
#if USE_STAGE_IN
|
||||
const PatchInput patchInput [[stage_in]],
|
||||
#else
|
||||
const OsdVertexBufferSet patchInput,
|
||||
#endif
|
||||
float2 position_in_patch [[position_in_patch]],
|
||||
uint patch_id [[patch_id]]
|
||||
)
|
||||
{
|
||||
OutputVertex out;
|
||||
|
||||
#if USE_STAGE_IN
|
||||
int3 patchParam = patchInput.patchParam;
|
||||
#else
|
||||
int3 patchParam = patchInput.patchParamBuffer[patch_id];
|
||||
#endif
|
||||
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) /
|
||||
exp2((float)refinementLevel - 1);
|
||||
|
||||
auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput);
|
||||
|
||||
out.position = (frameConsts.ModelViewMatrix * float4(patchVertex.position, 1.0f)).xyz;
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(patchVertex.position, 1.0f);
|
||||
|
||||
out.normal = mul(frameConsts.ModelViewMatrix, patchVertex.normal);
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
out.patchColor = getAdaptivePatchColor(patchParam, patchVertex.vSegments).xyz;
|
||||
#else
|
||||
out.patchColor = getAdaptivePatchColor(patchParam).xyz;
|
||||
#endif
|
||||
#elif SHADING_TYPE == SHADING_TYPE_NORMAL
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
out.patchColor = patchVertex.patchCoord.xyz;
|
||||
#endif
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_REGULAR
|
||||
const constant unsigned BSplineControlLineIndices[] = {
|
||||
0, 1, //Outer lines
|
||||
1, 2,
|
||||
2, 3,
|
||||
3, 7,
|
||||
7, 11,
|
||||
11, 15,
|
||||
15, 14,
|
||||
14, 13,
|
||||
13, 12,
|
||||
12, 8,
|
||||
8, 4,
|
||||
4, 0,
|
||||
|
||||
//Inner lines
|
||||
5, 6,
|
||||
6, 10,
|
||||
10, 9,
|
||||
9, 5,
|
||||
|
||||
//TL edge lines
|
||||
1, 5,
|
||||
4, 5,
|
||||
|
||||
//TR edge lines
|
||||
2, 6,
|
||||
6, 7,
|
||||
|
||||
//BL edge lines
|
||||
8, 9,
|
||||
9, 13,
|
||||
|
||||
//BR edge lines
|
||||
10, 14,
|
||||
10, 11
|
||||
};
|
||||
|
||||
vertex SolidColorVertex vertex_lines(
|
||||
const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
const device OsdPerPatchVertexBezier* osdPerPatchVertexBezier [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
uint vertex_id [[vertex_id]]
|
||||
)
|
||||
{
|
||||
const auto idx_size = sizeof(BSplineControlLineIndices) / sizeof(BSplineControlLineIndices[0]);
|
||||
const auto idx = vertex_id % idx_size;
|
||||
const auto patch_id = vertex_id / idx_size;
|
||||
|
||||
const auto in = osdPerPatchVertexBezier[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + BSplineControlLineIndices[idx]];
|
||||
|
||||
SolidColorVertex out;
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0);
|
||||
out.positionOut.z -= 0.001;
|
||||
|
||||
if(idx > 22) {
|
||||
out.setColor(half4(0,1,0,1));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.setColor(half4(1,0,0,1));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_BOUNDARY || OSD_PATCH_GREGORY
|
||||
const constant uint GregoryBasisControlLineIndices[] = {
|
||||
//Outer Edge
|
||||
0, 2,
|
||||
2, 16,
|
||||
16, 15,
|
||||
15, 17,
|
||||
17, 11,
|
||||
11, 10,
|
||||
10, 12,
|
||||
12, 6,
|
||||
6, 5,
|
||||
5, 7,
|
||||
7, 1,
|
||||
1, 0,
|
||||
|
||||
//Outside-Inside Edges
|
||||
1, 3,
|
||||
2, 4,
|
||||
16, 18,
|
||||
17, 19,
|
||||
11, 13,
|
||||
12, 14,
|
||||
6, 8,
|
||||
7, 9,
|
||||
|
||||
//Inner Edge
|
||||
3, 4,
|
||||
4, 18,
|
||||
18, 19,
|
||||
19, 13,
|
||||
13, 14,
|
||||
14, 8,
|
||||
8, 9,
|
||||
9, 3,
|
||||
};
|
||||
|
||||
|
||||
vertex SolidColorVertex vertex_lines(
|
||||
#if OSD_PATCH_GREGORY_BASIS
|
||||
const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
const device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
|
||||
#else
|
||||
const device PackedInputVertex* vertexBuffer [[buffer(OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX)]],
|
||||
#endif
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
uint vertex_id [[vertex_id]]
|
||||
)
|
||||
{
|
||||
const auto idx_size = sizeof(GregoryBasisControlLineIndices) / sizeof(GregoryBasisControlLineIndices[0]);
|
||||
const auto idx = vertex_id % idx_size;
|
||||
const auto patch_id = vertex_id / idx_size;
|
||||
|
||||
#if OSD_PATCH_GREGORY_BASIS
|
||||
const auto in = vertexBuffer[indicesBuffer[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + GregoryBasisControlLineIndices[idx]]];
|
||||
#else
|
||||
const auto in = vertexBuffer[patch_id * 20 + GregoryBasisControlLineIndices[idx]];
|
||||
#endif
|
||||
SolidColorVertex out;
|
||||
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.position, 1.0);
|
||||
out.positionOut.z -= 0.001;
|
||||
|
||||
if(idx > 22) {
|
||||
out.setColor(half4(0,1,0,1));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.setColor(half4(1,0,0,1));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_QUADS || OSD_PATCH_TRIANGLES
|
||||
|
||||
#if OSD_PATCH_QUADS
|
||||
const constant uint triangleIdx[6] = {
|
||||
0, 2, 1, 3, 2, 0
|
||||
};
|
||||
#endif
|
||||
|
||||
vertex OutputVertex vertex_main(
|
||||
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
uint vertex_id [[vertex_id]]
|
||||
)
|
||||
{
|
||||
#if OSD_PATCH_QUADS
|
||||
const auto quadId = vertex_id / 6;
|
||||
#else
|
||||
const auto primID = vertex_id / 3;
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_QUADS
|
||||
float3 p0 = vertexBuffer[indicesBuffer[quadId * 4 + 0]].position;
|
||||
float3 p1 = vertexBuffer[indicesBuffer[quadId * 4 + 1]].position;
|
||||
float3 p2 = vertexBuffer[indicesBuffer[quadId * 4 + 2]].position;
|
||||
float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position;
|
||||
#else
|
||||
float3 p0 = vertexBuffer[indicesBuffer[primID * 3 + 0]].position;
|
||||
float3 p1 = vertexBuffer[indicesBuffer[primID * 3 + 1]].position;
|
||||
float3 p2 = vertexBuffer[indicesBuffer[primID * 3 + 2]].position;
|
||||
float3 position = vertexBuffer[indicesBuffer[vertex_id]].position;
|
||||
#endif
|
||||
|
||||
float3 normal = normalize(cross(p2 - p1, p0 - p1));
|
||||
|
||||
|
||||
OutputVertex out;
|
||||
out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz;
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
|
||||
out.normal = (frameConsts.ModelViewMatrix * float4(normal,0.0)).xyz;
|
||||
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
out.patchColor = out.normal;
|
||||
#endif
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
vertex SolidColorVertex vertex_lines(
|
||||
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
uint vertex_id [[vertex_id]]
|
||||
)
|
||||
{
|
||||
#if OSD_PATCH_QUADS
|
||||
const auto quadId = vertex_id / 6;
|
||||
#else
|
||||
const auto primID = vertex_id / 3;
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_QUADS
|
||||
float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position;
|
||||
#else
|
||||
float3 position = vertexBuffer[indicesBuffer[vertex_id]].position;
|
||||
#endif
|
||||
|
||||
SolidColorVertex out;
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
fragment half4 fragment_solidcolor(SolidColorVertex in [[stage_in]])
|
||||
{
|
||||
return in.getColor();
|
||||
}
|
||||
|
||||
|
||||
fragment float4 fragment_main(OutputVertex in [[stage_in]],
|
||||
const constant Light* lightData [[buffer(0)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(1)]],
|
||||
const constant float4& shade [[buffer(2)]])
|
||||
{
|
||||
float4 color;
|
||||
|
||||
#if SHADING_TYPE == SHADING_TYPE_MATERIAL
|
||||
const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f);
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH
|
||||
const float3 diffuseColor = in.patchColor;
|
||||
#else
|
||||
#endif
|
||||
#if SHADING_TYPE == SHADING_TYPE_NORMAL
|
||||
color.xyz = normalize(in.normal) * 0.5 + 0.5;
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
color.xy = in.patchColor.xy;
|
||||
color.z = 0;
|
||||
#else
|
||||
color.xyz = lighting(diffuseColor, lightData, in.position, normalize(in.normal));
|
||||
#endif
|
||||
// color.xyz = pow(color.xyz, 2.2);
|
||||
color.w = 1;
|
||||
return max(color,shade);
|
||||
}
|
1265
examples/mtlViewer/mtlViewer.mm
Normal file
1265
examples/mtlViewer/mtlViewer.mm
Normal file
File diff suppressed because it is too large
Load Diff
@ -62,7 +62,7 @@ if (NOT NO_LIB)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(OPENGL_FOUND OR OPENCL_FOUND OR DXSDK_FOUND)
|
||||
if(OPENGL_FOUND OR OPENCL_FOUND OR DXSDK_FOUND OR METAL_FOUND)
|
||||
add_subdirectory(tools/stringify)
|
||||
endif()
|
||||
|
||||
@ -96,6 +96,14 @@ if (NOT NO_LIB)
|
||||
)
|
||||
endif()
|
||||
|
||||
if( METAL_FOUND )
|
||||
include_directories( "${METAL_INCLUDE_DIR}" )
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${METAL_LIBRARIES}
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||
endif()
|
||||
|
||||
if ( OPENCL_FOUND )
|
||||
include_directories( "${OPENCL_INCLUDE_DIRS}" )
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
@ -142,6 +150,7 @@ if (NOT NO_LIB)
|
||||
$<TARGET_OBJECTS:far_obj>
|
||||
$<TARGET_OBJECTS:osd_cpu_obj>
|
||||
)
|
||||
|
||||
set_target_properties(osd_static_cpu
|
||||
PROPERTIES
|
||||
OUTPUT_NAME osdCPU
|
||||
@ -159,7 +168,7 @@ if (NOT NO_LIB)
|
||||
# this macro uses FindCUDA.cmake to compile .cu kernel files
|
||||
# the target then adds the other obj dependencies and include files
|
||||
_add_possibly_cuda_library(osd_static_gpu "opensubdiv"
|
||||
STATIC
|
||||
STATIC
|
||||
version.cpp
|
||||
$<TARGET_OBJECTS:osd_gpu_obj>
|
||||
${CUDA_KERNEL_FILES}
|
||||
@ -244,6 +253,113 @@ if (NOT NO_LIB)
|
||||
|
||||
endif()
|
||||
|
||||
# Build frameworks ----------------------------------
|
||||
if(APPLE)
|
||||
get_directory_property(OSD_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/osd DEFINITION PUBLIC_HEADER_FILES)
|
||||
get_directory_property(FAR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/far DEFINITION PUBLIC_HEADER_FILES)
|
||||
get_directory_property(SDC_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/sdc DEFINITION PUBLIC_HEADER_FILES)
|
||||
get_directory_property(HBR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/hbr DEFINITION PUBLIC_HEADER_FILES)
|
||||
get_directory_property(VTR_HEADER_FILES DIRECTORY ${CMAKE_SOURCE_DIR}/opensubdiv/vtr DEFINITION PUBLIC_HEADER_FILES)
|
||||
|
||||
|
||||
foreach(file ${OSD_HEADER_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES "osd/${file}")
|
||||
endforeach(file)
|
||||
|
||||
foreach(file ${FAR_HEADER_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES "far/${file}")
|
||||
endforeach(file)
|
||||
|
||||
foreach(file ${SDC_HEADER_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES "sdc/${file}")
|
||||
endforeach(file)
|
||||
|
||||
foreach(file ${HBR_HEADER_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES "hbr/${file}")
|
||||
endforeach(file)
|
||||
|
||||
foreach(file ${VTR_HEADER_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES "vtr/${file}")
|
||||
endforeach(file)
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES "version.h")
|
||||
|
||||
#static framework
|
||||
add_library(osd_static_framework
|
||||
STATIC
|
||||
version.cpp
|
||||
$<TARGET_OBJECTS:sdc_obj>
|
||||
$<TARGET_OBJECTS:vtr_obj>
|
||||
$<TARGET_OBJECTS:far_obj>
|
||||
$<TARGET_OBJECTS:osd_cpu_obj>
|
||||
$<TARGET_OBJECTS:osd_gpu_obj>
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
osd_static_framework
|
||||
PROPERTIES
|
||||
FRAMEWORK true
|
||||
INSTALL_NAME_DIR "@rpath/OpenSubdiv.framework/OpenSubdiv"
|
||||
INSTALL_RPATH "@executable_path/Frameworks;@loader_path/Frameworks"
|
||||
OUTPUT_NAME OpenSubdiv
|
||||
CLEAN_DIRECT_OUTPUT true
|
||||
)
|
||||
|
||||
target_link_libraries(osd_static_framework
|
||||
${PLATFORM_CPU_LIBRARIES} ${PLATFORM_GPU_LIBRARIES}
|
||||
)
|
||||
|
||||
install( TARGETS osd_static_framework
|
||||
LIBRARY DESTINATION "${CMAKE_LIBDIR_BASE}"
|
||||
FRAMEWORK DESTINATION "${CMAKE_LIBDIR_BASE}"
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
|
||||
ARCHIVE DESTINATION "${CMAKE_LIBDIR_BASE}")
|
||||
|
||||
|
||||
#shared framework
|
||||
add_library(osd_dynamic_framework
|
||||
SHARED
|
||||
version.cpp
|
||||
$<TARGET_OBJECTS:sdc_obj>
|
||||
$<TARGET_OBJECTS:vtr_obj>
|
||||
$<TARGET_OBJECTS:far_obj>
|
||||
$<TARGET_OBJECTS:osd_cpu_obj>
|
||||
$<TARGET_OBJECTS:osd_gpu_obj>
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
osd_dynamic_framework
|
||||
PROPERTIES
|
||||
RPATH true
|
||||
FRAMEWORK true
|
||||
INSTALL_NAME_DIR "@rpath/OpenSubdiv.framework/OpenSubdiv"
|
||||
INSTALL_RPATH "@executable_path/Frameworks;@loader_path/Frameworks"
|
||||
OUTPUT_NAME OpenSubdiv
|
||||
CLEAN_DIRECT_OUTPUT true
|
||||
)
|
||||
|
||||
target_link_libraries(osd_dynamic_framework
|
||||
${PLATFORM_CPU_LIBRARIES} ${PLATFORM_GPU_LIBRARIES}
|
||||
)
|
||||
|
||||
install( TARGETS osd_dynamic_framework
|
||||
FRAMEWORK DESTINATION "${CMAKE_LIBDIR_BASE}"
|
||||
LIBRARY DESTINATION "${CMAKE_LIBDIR_BASE}"
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
|
||||
PRIVATE_HEADER DESTINATION "${CMAKE_INCDIR_BASE}"
|
||||
)
|
||||
|
||||
foreach(file ${PUBLIC_HEADER_FILES})
|
||||
add_custom_command(TARGET osd_dynamic_framework POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/opensubdiv/${file}" "$<TARGET_FILE_DIR:osd_dynamic_framework>/Headers/${file}"
|
||||
)
|
||||
endforeach(file)
|
||||
|
||||
add_custom_command(TARGET osd_dynamic_framework POST_BUILD
|
||||
COMMAND ln -sf "Versions/Current/Headers" "$<TARGET_FILE_DIR:osd_dynamic_framework>/../../Headers"
|
||||
)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -117,7 +117,7 @@ set(GL_PUBLIC_HEADERS
|
||||
glslPatchShaderSource.h
|
||||
)
|
||||
|
||||
if( OPENGL_FOUND OR OPENGLES_FOUND )
|
||||
if( (NOT NO_OPENGL) AND (OPENGL_FOUND OR OPENGLES_FOUND) )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cpuGLVertexBuffer.cpp
|
||||
glLegacyGregoryPatchTable.cpp
|
||||
@ -218,6 +218,55 @@ endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${DXSDK_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Metal code & dependencies
|
||||
set(METAL_PUBLIC_HEADERS
|
||||
mtlVertexBuffer.h
|
||||
mtlComputeEvaluator.h
|
||||
mtlLegacyGregoryPatchTable.h
|
||||
mtlPatchTable.h
|
||||
mtlVertexBuffer.h
|
||||
mtlMesh.h
|
||||
mtlPatchShaderSource.h
|
||||
mtlCommon.h
|
||||
)
|
||||
|
||||
|
||||
if( METAL_FOUND )
|
||||
set(METAL_SOURCE_FILES
|
||||
mtlVertexBuffer.mm
|
||||
mtlComputeEvaluator.mm
|
||||
mtlLegacyGregoryPatchTable.mm
|
||||
mtlPatchTable.mm
|
||||
mtlVertexBuffer.mm
|
||||
mtlPatchShaderSource.mm
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${METAL_SOURCE_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-fobjc-arc")
|
||||
|
||||
list(APPEND GPU_SOURCE_FILES ${METAL_SOURCE_FILES})
|
||||
|
||||
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES ${METAL_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
mtlComputeKernel.metal
|
||||
mtlPatchCommon.metal
|
||||
mtlPatchBSpline.metal
|
||||
mtlPatchGregory.metal
|
||||
mtlPatchGregoryBasis.metal
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${METAL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${METAL_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# OpenCL code & dependencies
|
||||
set(OPENCL_PUBLIC_HEADERS
|
||||
@ -330,12 +379,10 @@ if( GPU_SOURCE_FILES )
|
||||
${PUBLIC_HEADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
|
||||
set_target_properties(osd_gpu_obj
|
||||
PROPERTIES
|
||||
FOLDER "opensubdiv"
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
_add_doxy_headers( "${DOXY_HEADER_FILES}" )
|
||||
@ -350,7 +397,6 @@ install(
|
||||
GROUP_READ
|
||||
WORLD_READ )
|
||||
|
||||
|
||||
if (ANDROID)
|
||||
install(
|
||||
FILES
|
||||
|
52
opensubdiv/osd/mtlCommon.h
Normal file
52
opensubdiv/osd/mtlCommon.h
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_COMMON_H
|
||||
#define OPENSUBDIV3_OSD_MTL_COMMON_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLCommandQueue;
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Osd
|
||||
{
|
||||
class MTLContext
|
||||
{
|
||||
public:
|
||||
id<MTLDevice> device = nullptr;
|
||||
id<MTLCommandQueue> commandQueue = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
}
|
||||
|
||||
#endif //OPENSUBDIV3_OSD_MTL_COMMON_H
|
867
opensubdiv/osd/mtlComputeEvaluator.h
Normal file
867
opensubdiv/osd/mtlComputeEvaluator.h
Normal file
@ -0,0 +1,867 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/types.h"
|
||||
#include "../osd/bufferDescriptor.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
@protocol MTLLibrary;
|
||||
@protocol MTLComputePipelineState;
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Far
|
||||
{
|
||||
class StencilTable;
|
||||
class PatchTable;
|
||||
class LimitStencilTable;
|
||||
}
|
||||
|
||||
namespace Osd
|
||||
{
|
||||
class MTLStencilTable
|
||||
{
|
||||
public:
|
||||
template<typename STENCIL_TABLE, typename DEVICE_CONTEXT>
|
||||
static MTLStencilTable* Create(STENCIL_TABLE* stencilTable,
|
||||
DEVICE_CONTEXT context)
|
||||
{
|
||||
return new MTLStencilTable(stencilTable, context);
|
||||
}
|
||||
|
||||
|
||||
MTLStencilTable(Far::StencilTable const* stencilTable, MTLContext* context);
|
||||
MTLStencilTable(Far::LimitStencilTable const* stencilTable, MTLContext* context);
|
||||
~MTLStencilTable();
|
||||
|
||||
|
||||
id<MTLBuffer> GetSizesBuffer() const { return _sizesBuffer; }
|
||||
id<MTLBuffer> GetOffsetsBuffer() const { return _offsetsBuffer; }
|
||||
id<MTLBuffer> GetIndicesBuffer() const { return _indicesBuffer; }
|
||||
id<MTLBuffer> GetWeightsBuffer() const { return _weightsBuffer; }
|
||||
id<MTLBuffer> GetDuWeightsBuffer() const { return _duWeightsBuffer; }
|
||||
id<MTLBuffer> GetDvWeightsBuffer() const { return _dvWeightsBuffer; }
|
||||
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
id<MTLBuffer> _sizesBuffer;
|
||||
id<MTLBuffer> _offsetsBuffer;
|
||||
id<MTLBuffer> _indicesBuffer;
|
||||
id<MTLBuffer> _weightsBuffer;
|
||||
id<MTLBuffer> _duWeightsBuffer;
|
||||
id<MTLBuffer> _dvWeightsBuffer;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
class MTLComputeEvaluator
|
||||
{
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
|
||||
static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
MTLContext* context);
|
||||
|
||||
static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
MTLContext* context);
|
||||
|
||||
MTLComputeEvaluator();
|
||||
~MTLComputeEvaluator();
|
||||
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// Stencil evaluations with StencilTable
|
||||
///
|
||||
/// ----------------------------------------------------------------------
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// MTLBuffer interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
MTLComputeEvaluator const *instance,
|
||||
MTLContext* context)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
return instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
stencilTable,
|
||||
context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an instace on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
context);
|
||||
if (instance)
|
||||
{
|
||||
bool r = instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
stencilTable,
|
||||
context);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the dstBuffer
|
||||
///
|
||||
/// @param duBuffer Output U-derivative buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param duDesc vertex buffer descriptor for the duBuffer
|
||||
///
|
||||
/// @param dvBuffer Output V-derivative buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param dvDesc vertex buffer descriptor for the dvBuffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// SSBO interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
|
||||
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
MTLComputeEvaluator const *instance,
|
||||
MTLContext* context) {
|
||||
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
stencilTable,
|
||||
context);
|
||||
} else {
|
||||
// Create a pipeline state on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc, duDesc, dvDesc, context);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
stencilTable,
|
||||
context);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the compute pipeline on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
MTLContext* context) const
|
||||
{
|
||||
return EvalStencils(srcBuffer->BindMTLBuffer(context), srcDesc,
|
||||
dstBuffer->BindMTLBuffer(context), dstDesc,
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
0,
|
||||
0,
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils(),
|
||||
context);
|
||||
}
|
||||
|
||||
/// Dispatch the compute pipeline on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
|
||||
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
MTLContext* context) const
|
||||
{
|
||||
return EvalStencils(srcBuffer->BindVBO(), srcDesc,
|
||||
dstBuffer->BindVBO(), dstDesc,
|
||||
duBuffer->BindVBO(), duDesc,
|
||||
dvBuffer->BindVBO(), dvDesc,
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
stencilTable->GetDuWeightsBuffer(),
|
||||
stencilTable->GetDvWeightsBuffer(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils(),
|
||||
context);
|
||||
}
|
||||
|
||||
/// Dispatch the compute pipeline on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
|
||||
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
|
||||
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
|
||||
id<MTLBuffer> sizesBuffer,
|
||||
id<MTLBuffer> offsetsBuffer,
|
||||
id<MTLBuffer> indicesBuffer,
|
||||
id<MTLBuffer> weightsBuffer,
|
||||
id<MTLBuffer> duWeightsBuffer,
|
||||
id<MTLBuffer> dvWeightsBuffer,
|
||||
int start,
|
||||
int end,
|
||||
MTLContext* context) const;
|
||||
|
||||
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// Limit evaluations with PatchTable
|
||||
///
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
static bool EvalPatches(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLComputeEvaluator const *instance,
|
||||
MTLContext* context) {
|
||||
|
||||
if (instance) {
|
||||
return instance->EvalPatches(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
context);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(), context );
|
||||
if (instance) {
|
||||
bool r = instance->EvalPatches(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
context);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning an
|
||||
/// MTLBuffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param duBuffer
|
||||
///
|
||||
/// @param duDesc
|
||||
///
|
||||
/// @param dvBuffer
|
||||
///
|
||||
/// @param dvDesc
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
static bool EvalPatches(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
|
||||
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLComputeEvaluator* instance,
|
||||
MTLContext* context) {
|
||||
|
||||
if (instance) {
|
||||
return instance->EvalPatches(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
context);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc, duDesc, dvDesc, context);
|
||||
if (instance) {
|
||||
bool r = instance->EvalPatches(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
context);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBOBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
bool EvalPatches(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLContext* context) const {
|
||||
|
||||
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
|
||||
dstBuffer->BindVBO(), dstDesc,
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoords->BindVBO(),
|
||||
patchTable->GetPatchArrays(),
|
||||
patchTable->GetPatchIndexBuffer(),
|
||||
patchTable->GetPatchParamBuffer(),
|
||||
context);
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function with derivatives. This function has
|
||||
/// a same signature as other device kernels have so that it can be
|
||||
/// called in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param duBuffer Output U-derivatives buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param duDesc vertex buffer descriptor for the duBuffer
|
||||
///
|
||||
/// @param dvBuffer Output V-derivatives buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dvDesc vertex buffer descriptor for the dvBuffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
bool EvalPatches(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *duBuffer, BufferDescriptor const &duDesc,
|
||||
DST_BUFFER *dvBuffer, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLContext* context) const {
|
||||
|
||||
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
|
||||
dstBuffer->BindVBO(), dstDesc,
|
||||
duBuffer->BindVBO(), duDesc,
|
||||
dvBuffer->BindVBO(), dvDesc,
|
||||
numPatchCoords,
|
||||
patchCoords->BindVBO(),
|
||||
patchTable->GetPatchArrays(),
|
||||
patchTable->GetPatchIndexBuffer(),
|
||||
patchTable->GetPatchParamBuffer(),
|
||||
context);
|
||||
}
|
||||
|
||||
bool EvalPatches(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
|
||||
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
|
||||
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
id<MTLBuffer> patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
id<MTLBuffer> patchIndexBuffer,
|
||||
id<MTLBuffer> patchParamsBuffer,
|
||||
MTLContext* context) const;
|
||||
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a GL
|
||||
/// buffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a GL
|
||||
/// buffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
static bool EvalPatchesVarying(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLComputeEvaluator const *instance,
|
||||
MTLContext* deviceContext) {
|
||||
|
||||
if (instance) {
|
||||
return instance->EvalPatchesVarying(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
deviceContext);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalPatchesVarying(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable,
|
||||
deviceContext);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBOBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
bool EvalPatchesVarying(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLContext* deviceContext) const {
|
||||
|
||||
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
|
||||
dstBuffer->BindVBO(), dstDesc,
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoords->BindVBO(),
|
||||
patchTable->GetVaryingPatchArrays(),
|
||||
patchTable->GetVaryingPatchIndexBuffer(),
|
||||
patchTable->GetPatchParamBuffer(),
|
||||
deviceContext
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a GL
|
||||
/// buffer object of source data
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a GL
|
||||
/// buffer object of destination data
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param fvarChannel face-varying channel
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
static bool EvalPatchesFaceVarying(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
int fvarChannel,
|
||||
MTLComputeEvaluator const *instance,
|
||||
MTLContext* deviceContext) {
|
||||
|
||||
if (instance) {
|
||||
return instance->EvalPatchesFaceVarying(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable, fvarChannel,
|
||||
deviceContext);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalPatchesFaceVarying(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
numPatchCoords, patchCoords,
|
||||
patchTable, fvarChannel,
|
||||
deviceContext);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBOBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
/// must have BindVBO() method returning an
|
||||
/// array of PatchCoord struct in VBO.
|
||||
///
|
||||
/// @param patchTable MTLPatchTable or equivalent
|
||||
///
|
||||
/// @param fvarChannel face-varying channel
|
||||
///
|
||||
/// @param deviceContext used to obtain the MTLDevice objcet and command queue
|
||||
/// to obtain command buffers from.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER,
|
||||
typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
|
||||
bool EvalPatchesFaceVarying(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PATCHCOORD_BUFFER *patchCoords,
|
||||
PATCH_TABLE *patchTable,
|
||||
MTLContext* deviceContext,
|
||||
int fvarChannel = 0
|
||||
) const {
|
||||
|
||||
return EvalPatches(srcBuffer->BindVBO(), srcDesc,
|
||||
dstBuffer->BindVBO(), dstDesc,
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoords->BindVBO(),
|
||||
patchTable->GetFVarPatchArrays(fvarChannel),
|
||||
patchTable->GetFVarPatchIndexBuffer(fvarChannel),
|
||||
patchTable->GetFVarPatchParamBuffer(fvarChannel),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
/// Configure compute pipline state. Returns false if it fails to create the pipeline state.
|
||||
bool Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
MTLContext* context);
|
||||
|
||||
/// Wait for the dispatched kernel to finish.
|
||||
static void Synchronize(MTLContext* context);
|
||||
|
||||
private:
|
||||
|
||||
id<MTLLibrary> _computeLibrary;
|
||||
id<MTLComputePipelineState> _evalStencils;
|
||||
id<MTLComputePipelineState> _evalPatches;
|
||||
id<MTLBuffer> _parameterBuffer;
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} //end namespace OpenSubdiv
|
||||
#endif // OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
|
473
opensubdiv/osd/mtlComputeEvaluator.mm
Normal file
473
opensubdiv/osd/mtlComputeEvaluator.mm
Normal file
@ -0,0 +1,473 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/mtlComputeEvaluator.h"
|
||||
#include "../osd/mtlPatchShaderSource.h"
|
||||
|
||||
#include <vector>
|
||||
#include <Metal/Metal.h>
|
||||
#include <simd/simd.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "../far/stencilTable.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
|
||||
|
||||
#define PARAMETER_BUFFER_INDEX 0
|
||||
#define SIZES_BUFFER_INDEX 1
|
||||
#define OFFSETS_BUFFER_INDEX 2
|
||||
#define INDICES_BUFFER_INDEX 3
|
||||
#define WEIGHTS_BUFFER_INDEX 4
|
||||
#define DST_VERTEX_BUFFER_INDEX 5
|
||||
#define SRC_VERTEX_BUFFER_INDEX 6
|
||||
#define DU_WEIGHTS_BUFFER_INDEX 7
|
||||
#define DV_WEIGHTS_BUFFER_INDEX 8
|
||||
#define DU_DERIVATIVE_BUFFER_INDEX 9
|
||||
#define DV_DERIVATIVE_BUFFER_INDEX 10
|
||||
#define PATCH_ARRAYS_BUFFER_INDEX 11
|
||||
#define PATCH_COORDS_BUFFER_INDEX 12
|
||||
#define PATCH_INDICES_BUFFER_INDEX 13
|
||||
#define PATCH_PARAMS_BUFFER_INDEX 14
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
namespace Osd {
|
||||
|
||||
namespace mtl
|
||||
{
|
||||
struct PatchCoord
|
||||
{
|
||||
int arrayIndex;
|
||||
int patchIndex;
|
||||
int vertIndex;
|
||||
float s;
|
||||
float t;
|
||||
};
|
||||
|
||||
struct PatchParam
|
||||
{
|
||||
uint field0;
|
||||
uint field1;
|
||||
float sharpness;
|
||||
};
|
||||
|
||||
struct KernelUniformArgs
|
||||
{
|
||||
int batchStart;
|
||||
int batchEnd;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
|
||||
simd::int3 duDesc;
|
||||
simd::int3 dvDesc;
|
||||
};
|
||||
} //end namespace mtl
|
||||
|
||||
static const char *KernelSource =
|
||||
#include "mtlComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
template <typename T>
|
||||
static id<MTLBuffer> createBuffer(const std::vector<T> &vec,
|
||||
MTLContext* context)
|
||||
{
|
||||
const auto length = sizeof(T) * vec.size();
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceOptionCPUCacheModeDefault];
|
||||
#elif TARGET_OS_OSX
|
||||
@autoreleasepool {
|
||||
auto cmdBuf = [context->commandQueue commandBuffer];
|
||||
auto blitEncoder = [cmdBuf blitCommandEncoder];
|
||||
|
||||
auto stageBuffer = [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceOptionCPUCacheModeDefault];
|
||||
|
||||
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
|
||||
|
||||
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuf commit];
|
||||
[cmdBuf waitUntilCompleted];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[stageBuffer release];
|
||||
#endif
|
||||
|
||||
return finalBuffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
using namespace Osd;
|
||||
|
||||
MTLStencilTable::MTLStencilTable(Far::StencilTable const *stencilTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0)
|
||||
{
|
||||
auto sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
|
||||
|
||||
_sizesBuffer.label = @"StencilTable Sizes";
|
||||
_offsetsBuffer.label = @"StencilTable Offsets";
|
||||
_indicesBuffer.label = @"StencilTable Indices";
|
||||
_weightsBuffer.label = @"StencilTable Weights";
|
||||
}
|
||||
|
||||
_duWeightsBuffer = nil;
|
||||
_dvWeightsBuffer = nil;
|
||||
}
|
||||
|
||||
MTLStencilTable::MTLStencilTable(Far::LimitStencilTable const *stencilTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0)
|
||||
{
|
||||
auto sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
|
||||
_duWeightsBuffer = createBuffer(stencilTable->GetDuWeights(), context);
|
||||
_dvWeightsBuffer = createBuffer(stencilTable->GetDvWeights(), context);
|
||||
|
||||
_sizesBuffer.label = @"StencilTable Sizes";
|
||||
_offsetsBuffer.label = @"StencilTable Offsets";
|
||||
_indicesBuffer.label = @"StencilTable Indices";
|
||||
_weightsBuffer.label = @"StencilTable Weights";
|
||||
_duWeightsBuffer.label = @"StencilTable duWeights";
|
||||
_dvWeightsBuffer.label = @"StencilTable dvWeights";
|
||||
}
|
||||
}
|
||||
|
||||
MTLStencilTable::~MTLStencilTable() {}
|
||||
|
||||
MTLComputeEvaluator *MTLComputeEvaluator::Create(
|
||||
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
auto instance = new MTLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, context))
|
||||
return instance;
|
||||
|
||||
delete instance;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MTLComputeEvaluator *MTLComputeEvaluator::Create(
|
||||
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc, BufferDescriptor const &duvDesc, BufferDescriptor const &dvvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
auto instance = new MTLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, context))
|
||||
return instance;
|
||||
|
||||
delete instance;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
using namespace Osd;
|
||||
using namespace Far;
|
||||
|
||||
MTLCompileOptions *compileOptions = [[MTLCompileOptions alloc] init];
|
||||
compileOptions.preprocessorMacros = nil;
|
||||
|
||||
bool useDeriv = duDesc.length > 0 || dvDesc.length > 0;
|
||||
|
||||
if(useDeriv)
|
||||
{
|
||||
printf("Using OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES");
|
||||
}
|
||||
|
||||
#define DEFINE(x,y) @(#x) : @(y)
|
||||
auto preprocessor = @{
|
||||
DEFINE(LENGTH, srcDesc.length),
|
||||
DEFINE(SRC_STRIDE, srcDesc.stride),
|
||||
DEFINE(DST_STRIDE, dstDesc.stride),
|
||||
DEFINE(WORK_GROUP_SIZE, _workGroupSize),
|
||||
DEFINE(OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES, useDeriv),
|
||||
DEFINE(PARAMETER_BUFFER_INDEX,PARAMETER_BUFFER_INDEX),
|
||||
DEFINE(SIZES_BUFFER_INDEX,SIZES_BUFFER_INDEX),
|
||||
DEFINE(OFFSETS_BUFFER_INDEX,OFFSETS_BUFFER_INDEX),
|
||||
DEFINE(INDICES_BUFFER_INDEX,INDICES_BUFFER_INDEX),
|
||||
DEFINE(WEIGHTS_BUFFER_INDEX,WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(SRC_VERTEX_BUFFER_INDEX,SRC_VERTEX_BUFFER_INDEX),
|
||||
DEFINE(DST_VERTEX_BUFFER_INDEX,DST_VERTEX_BUFFER_INDEX),
|
||||
DEFINE(DU_WEIGHTS_BUFFER_INDEX,DU_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DV_WEIGHTS_BUFFER_INDEX,DV_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DU_DERIVATIVE_BUFFER_INDEX,DU_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(DV_DERIVATIVE_BUFFER_INDEX,DV_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(PATCH_ARRAYS_BUFFER_INDEX,PATCH_ARRAYS_BUFFER_INDEX),
|
||||
DEFINE(PATCH_COORDS_BUFFER_INDEX,PATCH_COORDS_BUFFER_INDEX),
|
||||
DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX),
|
||||
DEFINE(PATCH_PARAMS_BUFFER_INDEX,PATCH_PARAMS_BUFFER_INDEX),
|
||||
};
|
||||
#undef DEFINE
|
||||
|
||||
compileOptions.preprocessorMacros = preprocessor;
|
||||
|
||||
std::stringstream sourceString;
|
||||
sourceString << MTLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
sourceString << KernelSource;
|
||||
|
||||
NSError *err = nil;
|
||||
|
||||
_computeLibrary =
|
||||
[context->device newLibraryWithSource:@(sourceString.str().c_str())
|
||||
options:compileOptions
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[compileOptions release];
|
||||
#endif
|
||||
|
||||
if (!_computeLibrary)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Shader: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto evalStencilsFunction = [_computeLibrary newFunctionWithName:@"eval_stencils"];
|
||||
_evalStencils =
|
||||
[context->device newComputePipelineStateWithFunction:evalStencilsFunction
|
||||
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[evalStencilsFunction release];
|
||||
#endif
|
||||
|
||||
if (!_evalStencils)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_stencils: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto evalPatchesFunction = [_computeLibrary newFunctionWithName:@"eval_patches"];
|
||||
_evalPatches =
|
||||
[context->device newComputePipelineStateWithFunction:evalPatchesFunction
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[evalPatchesFunction release];
|
||||
#endif
|
||||
|
||||
if (!_evalPatches)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_patches: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
_parameterBuffer =
|
||||
[context->device newBufferWithLength:sizeof(mtl::KernelUniformArgs)
|
||||
options:MTLResourceOptionCPUCacheModeDefault];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MTLComputeEvaluator::MTLComputeEvaluator() : _workGroupSize(32) {}
|
||||
|
||||
MTLComputeEvaluator::~MTLComputeEvaluator()
|
||||
{
|
||||
#if !__has_feature(objc_arc)
|
||||
[_computeLibrary release];
|
||||
[_evalStencils release];
|
||||
[_evalPatches release];
|
||||
[_parameterBuffer release];
|
||||
#endif
|
||||
}
|
||||
|
||||
void MTLComputeEvaluator::Synchronize(MTLContext* context) { }
|
||||
|
||||
bool MTLComputeEvaluator::EvalStencils(
|
||||
id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
|
||||
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
|
||||
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
|
||||
id<MTLBuffer> sizesBuffer,
|
||||
id<MTLBuffer> offsetsBuffer,
|
||||
id<MTLBuffer> indicesBuffer,
|
||||
id<MTLBuffer> weightsBuffer,
|
||||
id<MTLBuffer> duWeightsBuffer,
|
||||
id<MTLBuffer> dvWeightsBuffer, int start, int end,
|
||||
MTLContext* context) const
|
||||
{
|
||||
if(_evalStencils == nil)
|
||||
return false;
|
||||
|
||||
auto count = end - start;
|
||||
if (count <= 0)
|
||||
return true;
|
||||
|
||||
assert(context != nullptr);
|
||||
|
||||
auto device = context->device;
|
||||
auto commandQueue = context->commandQueue;
|
||||
|
||||
assert(device != nil && commandQueue != nil);
|
||||
|
||||
mtl::KernelUniformArgs args;
|
||||
args.batchStart = start;
|
||||
args.batchEnd = end;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
|
||||
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
|
||||
|
||||
memcpy(_parameterBuffer.contents, &args, sizeof(args));
|
||||
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
|
||||
auto computeEncoder = [commandBuffer computeCommandEncoder];
|
||||
|
||||
[computeEncoder setBuffer:_parameterBuffer offset:0 atIndex:PARAMETER_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:sizesBuffer offset:0 atIndex:SIZES_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:weightsBuffer offset:0 atIndex:WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:offsetsBuffer offset:0 atIndex:OFFSETS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:indicesBuffer offset:0 atIndex:INDICES_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
|
||||
if(duWeightsBuffer && dvWeightsBuffer)
|
||||
{
|
||||
[computeEncoder setBuffer:duWeightsBuffer offset:0 atIndex:DU_WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvWeightsBuffer offset:0 atIndex:DV_WEIGHTS_BUFFER_INDEX];
|
||||
}
|
||||
[computeEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeEncoder setComputePipelineState:_evalStencils];
|
||||
|
||||
auto threadgroups = MTLSizeMake((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
|
||||
[computeEncoder dispatchThreadgroups:threadgroups
|
||||
threadsPerThreadgroup:threadsPerGroup];
|
||||
|
||||
[computeEncoder endEncoding];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MTLComputeEvaluator::EvalPatches(
|
||||
id<MTLBuffer> srcBuffer, const BufferDescriptor &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, const BufferDescriptor &dstDesc,
|
||||
id<MTLBuffer> duBuffer, const BufferDescriptor &duDesc,
|
||||
id<MTLBuffer> dvBuffer, const BufferDescriptor &dvDesc,
|
||||
int numPatchCoords,
|
||||
id<MTLBuffer> patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
id<MTLBuffer> patchIndexBuffer,
|
||||
id<MTLBuffer> patchParamsBuffer,
|
||||
MTLContext* context) const
|
||||
{
|
||||
if(_evalPatches == nil)
|
||||
return false;
|
||||
|
||||
assert(context != nullptr);
|
||||
|
||||
auto device = context->device;
|
||||
auto commandQueue = context->commandQueue;
|
||||
|
||||
assert(device != nil && commandQueue != nil);
|
||||
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
auto computeCommandEncoder = [commandBuffer computeCommandEncoder];
|
||||
|
||||
mtl::KernelUniformArgs args;
|
||||
args.batchStart = 0;
|
||||
args.batchEnd = numPatchCoords;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
|
||||
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
|
||||
|
||||
[computeCommandEncoder setBytes:&args length:sizeof(mtl::KernelUniformArgs) atIndex:PARAMETER_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:patchCoordsBuffer offset:0 atIndex:PATCH_COORDS_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:patchIndexBuffer offset:0 atIndex:PATCH_INDICES_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:patchParamsBuffer offset:0 atIndex:PATCH_PARAMS_BUFFER_INDEX];
|
||||
assert(patchArrays.size() == 2);
|
||||
[computeCommandEncoder setBytes:&patchArrays[0] length:sizeof(patchArrays[0]) * 2 atIndex:PATCH_ARRAYS_BUFFER_INDEX];
|
||||
[computeCommandEncoder setComputePipelineState:_evalPatches];
|
||||
|
||||
auto threadgroups =
|
||||
MTLSizeMake((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
|
||||
[computeCommandEncoder dispatchThreadgroups:threadgroups
|
||||
threadsPerThreadgroup:threadsPerGroup];
|
||||
|
||||
[computeCommandEncoder endEncoding];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
} //end namespace OpenSubdiv
|
292
opensubdiv/osd/mtlComputeKernel.metal
Normal file
292
opensubdiv/osd/mtlComputeKernel.metal
Normal file
@ -0,0 +1,292 @@
|
||||
#line 0 "osd/mtlComputeKernel.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include <metal_stdlib>
|
||||
|
||||
#ifndef OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
|
||||
#define OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES 0
|
||||
#endif
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct PatchCoord
|
||||
{
|
||||
int arrayIndex;
|
||||
int patchIndex;
|
||||
int vertIndex;
|
||||
float s;
|
||||
float t;
|
||||
};
|
||||
|
||||
struct PatchParam
|
||||
{
|
||||
uint field0;
|
||||
uint field1;
|
||||
float sharpness;
|
||||
};
|
||||
|
||||
struct KernelUniformArgs
|
||||
{
|
||||
int batchStart;
|
||||
int batchEnd;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
|
||||
int3 duDesc;
|
||||
int3 dvDesc;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(thread Vertex& v) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index, device const float* vertexBuffer, KernelUniformArgs args) {
|
||||
Vertex v;
|
||||
int vertexIndex = args.srcOffset + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = vertexBuffer[vertexIndex + i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(int index, Vertex v, device float* vertexBuffer, KernelUniformArgs args) {
|
||||
int vertexIndex = args.dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
vertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeVertexSeparate(int index, Vertex v, device float* dstVertexBuffer, KernelUniformArgs args) {
|
||||
int vertexIndex = args.dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(thread Vertex& v, const Vertex src, float weight) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] += weight * src.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDu(int index, Vertex du, device float* duDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int duIndex = args.duDesc.x + index * args.duDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++)
|
||||
{
|
||||
duDerivativeBuffer[duIndex + i] = du.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(int index, Vertex dv, device float* dvDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int dvIndex = args.dvDesc.x + index * args.dvDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++)
|
||||
{
|
||||
dvDerivativeBuffer[dvIndex + i] = dv.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
kernel void eval_stencils(
|
||||
uint thread_position_in_grid [[thread_position_in_grid]],
|
||||
const device int* sizes [[buffer(SIZES_BUFFER_INDEX)]],
|
||||
const device int* offsets [[buffer(OFFSETS_BUFFER_INDEX)]],
|
||||
const device int* indices [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
const device float* weights [[buffer(WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* srcVertices [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
|
||||
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
|
||||
const device float* duWeights [[buffer(DU_WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* dvWeights [[buffer(DV_WEIGHTS_BUFFER_INDEX)]],
|
||||
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
|
||||
)
|
||||
{
|
||||
auto current = thread_position_in_grid + args.batchStart;
|
||||
if(current >= args.batchEnd)
|
||||
return;
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
|
||||
auto offset = offsets[current];
|
||||
auto size = sizes[current];
|
||||
|
||||
for(auto stencil = 0; stencil < size; stencil++)
|
||||
{
|
||||
auto vindex = offset + stencil;
|
||||
addWithWeight(dst, readVertex(indices[vindex], srcVertices, args), weights[vindex]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst, dstVertexBuffer, args);
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
|
||||
Vertex du, dv;
|
||||
clear(du);
|
||||
clear(dv);
|
||||
|
||||
|
||||
for(auto i = 0; i < size; i++)
|
||||
{
|
||||
auto src = readVertex(indices[offset + i], srcVertices, args);
|
||||
addWithWeight(du, src, duWeights[offset + i]);
|
||||
addWithWeight(dv, src, dvWeights[offset + i]);
|
||||
}
|
||||
|
||||
writeDu(current, du, duDerivativeBuffer, args);
|
||||
writeDv(current, dv, dvDerivativeBuffer, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// PERFORMANCE: stride could be constant, but not as significant as length
|
||||
|
||||
//struct PatchArray {
|
||||
// int patchType;
|
||||
// int numPatches;
|
||||
// int indexBase; // an offset within the index buffer
|
||||
// int primitiveIdBase; // an offset within the patch param buffer
|
||||
//};
|
||||
// # of patcharrays is 1 or 2.
|
||||
|
||||
uint getDepth(uint patchBits) {
|
||||
return (patchBits & 0xf);
|
||||
}
|
||||
|
||||
float getParamFraction(uint patchBits) {
|
||||
uint nonQuadRoot = (patchBits >> 4) & 0x1;
|
||||
uint depth = getDepth(patchBits);
|
||||
if (nonQuadRoot == 1) {
|
||||
return 1.0f / float( 1 << (depth-1) );
|
||||
} else {
|
||||
return 1.0f / float( 1 << depth );
|
||||
}
|
||||
}
|
||||
|
||||
float2 normalizePatchCoord(uint patchBits, float2 uv) {
|
||||
float frac = getParamFraction(patchBits);
|
||||
|
||||
uint iu = (patchBits >> 22) & 0x3ff;
|
||||
uint iv = (patchBits >> 12) & 0x3ff;
|
||||
|
||||
// top left corner
|
||||
float pu = float(iu*frac);
|
||||
float pv = float(iv*frac);
|
||||
|
||||
// normalize u,v coordinates
|
||||
return float2((uv.x - pu) / frac, (uv.y - pv) / frac);
|
||||
}
|
||||
|
||||
bool isRegular(uint patchBits) {
|
||||
return (((patchBits >> 5) & 0x1u) != 0);
|
||||
}
|
||||
|
||||
int getNumControlVertices(int patchType) {
|
||||
switch(patchType) {
|
||||
case 3: return 4;
|
||||
case 6: return 16;
|
||||
case 9: return 20;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
kernel void eval_patches(
|
||||
uint thread_position_in_grid [[thread_position_in_grid]],
|
||||
const constant uint4* patchArrays [[buffer(PATCH_ARRAYS_BUFFER_INDEX)]],
|
||||
const device PatchCoord* patchCoords [[buffer(PATCH_COORDS_BUFFER_INDEX)]],
|
||||
const device int* patchIndices [[buffer(PATCH_INDICES_BUFFER_INDEX)]],
|
||||
const device PatchParam* patchParams [[buffer(PATCH_PARAMS_BUFFER_INDEX)]],
|
||||
const device float* srcVertexBuffer [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
|
||||
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
|
||||
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
|
||||
)
|
||||
{
|
||||
auto current = thread_position_in_grid;
|
||||
auto patchCoord = patchCoords[current];
|
||||
auto patchIndex = patchIndices[patchCoord.patchIndex];
|
||||
auto patchArray = patchArrays[patchCoord.arrayIndex];
|
||||
auto patchBits = patchParams[patchIndex].field1;
|
||||
auto patchType = select(isRegular(patchBits), 6, patchArray.x);
|
||||
auto numControlVertices = getNumControlVertices(patchType);
|
||||
auto uv = normalizePatchCoord(patchBits, float2(patchCoord.s, patchCoord.t));
|
||||
auto dScale = float(1 << getDepth(patchBits));
|
||||
auto boundry = int((patchBits >> 8) & 0xFU);
|
||||
|
||||
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
|
||||
|
||||
|
||||
if(patchType == 3) {
|
||||
OsdGetBilinearPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
} else if(patchType == 6) {
|
||||
OsdGetBSplinePatchWeights(uv.x, uv.y, dScale, boundry, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
} else if(patchType == 9) {
|
||||
OsdGetGregoryPatchWeights(uv.x, uv.y, dScale, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
}
|
||||
|
||||
Vertex dst, du, dv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
|
||||
|
||||
auto indexBase = patchArray.z + numControlVertices * (patchCoord.patchIndex - patchArray.w);
|
||||
for(auto cv = 0; cv < numControlVertices; cv++)
|
||||
{
|
||||
auto index = patchIndices[indexBase + cv];
|
||||
auto src = readVertex(index, srcVertexBuffer, args);
|
||||
addWithWeight(dst, src, wP[cv]);
|
||||
addWithWeight(du, src, wDs[cv]);
|
||||
addWithWeight(dv, src, wDt[cv]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst, dstVertexBuffer, args);
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_DERIVATIVES
|
||||
if(args.duDesc.y > 0)
|
||||
writeDu(current, du, duDerivativeBuffer, args);
|
||||
|
||||
if(args.dvDesc.y > 0)
|
||||
writeDv(current, dv, dvDerivativeBuffer, args);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
90
opensubdiv/osd/mtlLegacyGregoryPatchTable.h
Normal file
90
opensubdiv/osd/mtlLegacyGregoryPatchTable.h
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Osd
|
||||
{
|
||||
class MTLLegacyGregoryPatchTable
|
||||
: private NonCopyable<MTLLegacyGregoryPatchTable>
|
||||
{
|
||||
public:
|
||||
~MTLLegacyGregoryPatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTable, context);
|
||||
}
|
||||
|
||||
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, MTLContext* context);
|
||||
|
||||
void UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context);
|
||||
|
||||
id<MTLBuffer> GetVertexBuffer() const
|
||||
{
|
||||
return _vertexBuffer;
|
||||
}
|
||||
|
||||
id<MTLBuffer> GetVertexValenceBuffer() const
|
||||
{
|
||||
return _vertexValenceBuffer;
|
||||
}
|
||||
|
||||
id<MTLBuffer> GetQuadOffsetsBuffer() const
|
||||
{
|
||||
return _quadOffsetsBuffer;
|
||||
}
|
||||
|
||||
int GetQuadOffsetsBase(Far::PatchDescriptor::Type type)
|
||||
{
|
||||
if(type == Far::PatchDescriptor::GREGORY_BOUNDARY)
|
||||
return _quadOffsetsBase[1];
|
||||
return _quadOffsetsBase[0];
|
||||
}
|
||||
|
||||
private:
|
||||
id<MTLBuffer> _vertexBuffer;
|
||||
id<MTLBuffer> _vertexValenceBuffer;
|
||||
id<MTLBuffer> _quadOffsetsBuffer;
|
||||
int _quadOffsetsBase[2];
|
||||
};
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} //end namespace OpenSuddiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
100
opensubdiv/osd/mtlLegacyGregoryPatchTable.mm
Normal file
100
opensubdiv/osd/mtlLegacyGregoryPatchTable.mm
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/mtlLegacyGregoryPatchTable.h"
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
namespace Osd {
|
||||
|
||||
static id<MTLBuffer> createBuffer(const void* data, const size_t length,
|
||||
MTLContext* context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
auto cmdBuf = [context->commandQueue commandBuffer];
|
||||
auto blitEncoder = [cmdBuf blitCommandEncoder];
|
||||
|
||||
auto stageBuffer = [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
|
||||
|
||||
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
|
||||
|
||||
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuf commit];
|
||||
[cmdBuf waitUntilCompleted];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[stageBuffer release];
|
||||
#endif
|
||||
|
||||
return finalBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
MTLLegacyGregoryPatchTable::~MTLLegacyGregoryPatchTable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MTLLegacyGregoryPatchTable* MTLLegacyGregoryPatchTable::Create(const Far::PatchTable *farPatchTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
auto pt = new MTLLegacyGregoryPatchTable();
|
||||
auto& vertexValenceTable = farPatchTable->GetVertexValenceTable();
|
||||
auto& quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
if(!vertexValenceTable.empty())
|
||||
{
|
||||
pt->_vertexValenceBuffer = createBuffer(vertexValenceTable.data(), vertexValenceTable.size() * sizeof(vertexValenceTable[0]), context);
|
||||
}
|
||||
|
||||
if(!quadOffsetsTable.empty())
|
||||
{
|
||||
pt->_quadOffsetsBuffer = createBuffer(quadOffsetsTable.data(), quadOffsetsTable.size() * sizeof(quadOffsetsTable[0]), context);
|
||||
}
|
||||
|
||||
pt->_quadOffsetsBase[0] = 0;
|
||||
pt->_quadOffsetsBase[1] = 0;
|
||||
|
||||
for(auto i = 0; i < farPatchTable->GetNumPatchArrays(); i++)
|
||||
{
|
||||
if(farPatchTable->GetPatchArrayDescriptor(i).GetType() == Far::PatchDescriptor::GREGORY)
|
||||
{
|
||||
pt->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
void MTLLegacyGregoryPatchTable::UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context)
|
||||
{
|
||||
_vertexBuffer = vbo;
|
||||
}
|
||||
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
} //end namespace OpenSubdiv
|
46
opensubdiv/osd/mtlMesh.h
Normal file
46
opensubdiv/osd/mtlMesh.h
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_MESH_H
|
||||
#define OPENSUBDIV3_OSD_MTL_MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/mesh.h"
|
||||
#include "../osd/mtlPatchTable.h"
|
||||
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Osd
|
||||
{
|
||||
typedef MeshInterface<MTLPatchTable> MTLMeshInterface;
|
||||
} // end namespace Osd
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_MESH_H
|
1
opensubdiv/osd/mtlMesh.mm
Normal file
1
opensubdiv/osd/mtlMesh.mm
Normal file
@ -0,0 +1 @@
|
||||
#import "../osd/mtlMesh.h"
|
238
opensubdiv/osd/mtlPatchBSpline.metal
Normal file
238
opensubdiv/osd/mtlPatchBSpline.metal
Normal file
@ -0,0 +1,238 @@
|
||||
#line 0 "osd/mtlPatchBSpline.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 vertexPosition,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 ModelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = vertexPosition;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(ModelViewProjectionMatrix, vertexPosition);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchBSplineFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* patch
|
||||
#if !USE_PTVS_FACTORS
|
||||
,device OsdPerPatchTessFactors& patchFactors
|
||||
#endif
|
||||
,device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
OsdGetTessLevelsAdaptiveLimitPoints(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patch,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchBSplineFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
osdBuffer.perPatchVertexBuffer + patchID * CONTROL_POINTS_PER_PATCH,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
quadFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchVertexBSpline(patchParam, ID, patchVertices, osdBuffers.perPatchVertexBuffer[ControlID]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename PerPatchVertexBezier>
|
||||
OsdPatchVertex ds_regular_patches(
|
||||
const float TessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterHi,
|
||||
float4 tessOuterLo,
|
||||
#endif
|
||||
PerPatchVertexBezier cv,
|
||||
int3 patchParam,
|
||||
float2 domainCoord)
|
||||
{
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P, dPu, dPv;
|
||||
float3 N, dNu, dNv;
|
||||
float2 vSegments;
|
||||
#if !USE_PTVS_FACTORS
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
#else
|
||||
auto transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
float4 tessLevelMin = float4(1)
|
||||
+ float4(((transitionMask & 8) >> 3),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
((transitionMask & 4) >> 2));
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
tessLevelMin,
|
||||
float4(0));
|
||||
#endif
|
||||
|
||||
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv, vSegments);
|
||||
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
output.vSegments = vSegments;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
output.position = P;
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexBezier>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexBezier osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_regular_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterHi,
|
||||
osdPatch.tessOuterLo,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
||||
|
2072
opensubdiv/osd/mtlPatchCommon.metal
Normal file
2072
opensubdiv/osd/mtlPatchCommon.metal
Normal file
File diff suppressed because it is too large
Load Diff
195
opensubdiv/osd/mtlPatchGregory.metal
Normal file
195
opensubdiv/osd/mtlPatchGregory.metal
Normal file
@ -0,0 +1,195 @@
|
||||
#line 0 "osd/mtlPatchGregory.metal"
|
||||
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup OsdPerVertexGregory& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerVertexGregory(vertexId, position.xyz, hullVertex, osdBuffers);
|
||||
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
|
||||
OsdGetTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patchVertices[0].P,
|
||||
patchVertices[3].P,
|
||||
patchVertices[2].P,
|
||||
patchVertices[1].P,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner
|
||||
);
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchVertexGregory(
|
||||
patchParam,
|
||||
ID,
|
||||
PrimitiveID,
|
||||
patchVertices,
|
||||
osdBuffers.perPatchVertexBuffer[ControlID],
|
||||
osdBuffers);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename PerPatchVertexGregory>
|
||||
OsdPatchVertex ds_gregory_patches(
|
||||
PerPatchVertexGregory patch,
|
||||
int3 patchParam,
|
||||
float2 UV
|
||||
)
|
||||
{
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
float3 cv[20];
|
||||
cv[0] = patch[0].P;
|
||||
cv[1] = patch[0].Ep;
|
||||
cv[2] = patch[0].Em;
|
||||
cv[3] = patch[0].Fp;
|
||||
cv[4] = patch[0].Fm;
|
||||
|
||||
cv[5] = patch[1].P;
|
||||
cv[6] = patch[1].Ep;
|
||||
cv[7] = patch[1].Em;
|
||||
cv[8] = patch[1].Fp;
|
||||
cv[9] = patch[1].Fm;
|
||||
|
||||
cv[10] = patch[2].P;
|
||||
cv[11] = patch[2].Ep;
|
||||
cv[12] = patch[2].Em;
|
||||
cv[13] = patch[2].Fp;
|
||||
cv[14] = patch[2].Fm;
|
||||
|
||||
cv[15] = patch[3].P;
|
||||
cv[16] = patch[3].Ep;
|
||||
cv[17] = patch[3].Em;
|
||||
cv[18] = patch[3].Fp;
|
||||
cv[19] = patch[3].Fm;
|
||||
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = P;
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_gregory_patches(
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord);
|
||||
}
|
199
opensubdiv/osd/mtlPatchGregoryBasis.metal
Normal file
199
opensubdiv/osd/mtlPatchGregoryBasis.metal
Normal file
@ -0,0 +1,199 @@
|
||||
#line 0 "osd/mtlPatchGregoryBasis.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
|
||||
OsdGetTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patchVertices[0].position.xyz,
|
||||
patchVertices[3].position.xyz,
|
||||
patchVertices[2].position.xyz,
|
||||
patchVertices[1].position.xyz,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner
|
||||
);
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
//Does nothing, all transforms are in the PTVS
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define USE_128BIT_GREGORY_BASIS_INDICES_READ 1
|
||||
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex ds_gregory_basis_patches(
|
||||
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis patch,
|
||||
#else
|
||||
const device OsdInputVertexType* patch,
|
||||
const device unsigned* patchIndices,
|
||||
#endif
|
||||
int3 patchParam,
|
||||
float2 UV
|
||||
)
|
||||
{
|
||||
OsdPatchVertex output;
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
#if USE_STAGE_IN
|
||||
float3 cv[20];
|
||||
for(int i = 0; i < 20; i++)
|
||||
cv[i] = patch[i].position;
|
||||
#else
|
||||
#if USE_128BIT_GREGORY_BASIS_INDICES_READ
|
||||
float3 cv[20];
|
||||
for(int i = 0; i < 5; i++) {
|
||||
int4 indices = ((device int4*)patchIndices)[i];
|
||||
|
||||
int n = i * 4;
|
||||
cv[n + 0] = (patch + indices[0])->position;
|
||||
cv[n + 1] = (patch + indices[1])->position;
|
||||
cv[n + 2] = (patch + indices[2])->position;
|
||||
cv[n + 3] = (patch + indices[3])->position;
|
||||
}
|
||||
#else
|
||||
float3 cv[20];
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
cv[i] = patch[patchIndices[i]].position;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
output.position = P;
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_gregory_basis_patches(
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.vertexBuffer,
|
||||
osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
54
opensubdiv/osd/mtlPatchShaderSource.h
Normal file
54
opensubdiv/osd/mtlPatchShaderSource.h
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <string>
|
||||
#import "../version.h"
|
||||
#import "../far/patchDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class MTLPatchShaderSource {
|
||||
public:
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
136
opensubdiv/osd/mtlPatchShaderSource.mm
Normal file
136
opensubdiv/osd/mtlPatchShaderSource.mm
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/mtlPatchShaderSource.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static std::string commonShaderSource(
|
||||
#include "mtlPatchCommon.gen.h"
|
||||
);
|
||||
static std::string patchBasisShaderSource(
|
||||
#include "patchBasisCommon.gen.h"
|
||||
);
|
||||
static std::string bsplineShaderSource(
|
||||
#include "mtlPatchBSpline.gen.h"
|
||||
);
|
||||
static std::string gregoryShaderSource(
|
||||
#include "mtlPatchGregory.gen.h"
|
||||
);
|
||||
static std::string gregoryBasisShaderSource(
|
||||
#include "mtlPatchGregoryBasis.gen.h"
|
||||
);
|
||||
|
||||
static std::string GetPatchTypeDefine(Far::PatchDescriptor::Type type) {
|
||||
switch(type) {
|
||||
case Far::PatchDescriptor::LINES: return "#define OSD_PATCH_LINES 1\n";
|
||||
case Far::PatchDescriptor::TRIANGLES: return "#define OSD_PATCH_TRIANGLES 1\n";
|
||||
case Far::PatchDescriptor::QUADS: return "#define OSD_PATCH_QUADS 1\n";
|
||||
case Far::PatchDescriptor::REGULAR: return "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n";
|
||||
case Far::PatchDescriptor::GREGORY: return "#define OSD_PATCH_GREGORY 1\n";
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY: return "#define OSD_PATCH_GREGORY_BOUNDRY 1\n";
|
||||
case Far::PatchDescriptor::GREGORY_BASIS: return "#define OSD_PATCH_GREGORY_BASIS 1\n";
|
||||
default:
|
||||
assert("Unknown Far::PatchDescriptor::Type" && 0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GetPatchTypeSource(Far::PatchDescriptor::Type type) {
|
||||
switch(type) {
|
||||
case Far::PatchDescriptor::QUADS: return "";
|
||||
case Far::PatchDescriptor::REGULAR: return bsplineShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY: return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY: return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS: return gregoryBasisShaderSource;
|
||||
default:
|
||||
assert("Unknown Far::PatchDescriptor::Type" && 0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetCommonShaderSource() {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return std::string("#define OSD_METAL_IOS 1\n").append(commonShaderSource);
|
||||
#elif TARGET_OS_OSX
|
||||
return std::string("#define OSD_METAL_OSX 1\n").append(commonShaderSource);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetPatchBasisShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << "#define OSD_PATCH_BASIS_METAL 1\n";
|
||||
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
|
||||
ss << "define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n";
|
||||
#endif
|
||||
ss << patchBasisShaderSource;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
98
opensubdiv/osd/mtlPatchTable.h
Normal file
98
opensubdiv/osd/mtlPatchTable.h
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/patchDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Far
|
||||
{
|
||||
class PatchTable;
|
||||
}
|
||||
|
||||
namespace Osd
|
||||
{
|
||||
class MTLPatchTable : private NonCopyable<MTLPatchTable>
|
||||
{
|
||||
public:
|
||||
typedef id<MTLBuffer> VertexBufferBinding;
|
||||
|
||||
MTLPatchTable();
|
||||
~MTLPatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context)
|
||||
{
|
||||
return Create(farPatchTable, context);
|
||||
}
|
||||
|
||||
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, MTLContext* context);
|
||||
|
||||
PatchArrayVector const &GetPatchArrays() const { return _patchArrays; }
|
||||
id<MTLBuffer> GetPatchIndexBuffer() const { return _indexBuffer; }
|
||||
id<MTLBuffer> GetPatchParamBuffer() const { return _patchParamBuffer; }
|
||||
|
||||
PatchArrayVector const &GetVaryingPatchArrays() const { return _varyingPatchArrays; }
|
||||
id<MTLBuffer> GetVaryingPatchIndexBuffer() const { return _varyingPatchIndexBuffer; }
|
||||
|
||||
int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); }
|
||||
PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const { return _fvarPatchArrays[fvarChannel]; }
|
||||
id<MTLBuffer> GetFVarPatchIndexBuffer(int fvarChannel = 0) const { return _fvarIndexBuffers[fvarChannel]; }
|
||||
id<MTLBuffer> GetFVarPatchParamBuffer(int fvarChannel = 0) const { return _fvarParamBuffers[fvarChannel]; }
|
||||
|
||||
protected:
|
||||
bool allocate(Far::PatchTable const *farPatchTable, MTLContext* context);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
|
||||
id<MTLBuffer> _indexBuffer;
|
||||
id<MTLBuffer> _patchParamBuffer;
|
||||
|
||||
PatchArrayVector _varyingPatchArrays;
|
||||
|
||||
id<MTLBuffer> _varyingPatchIndexBuffer;
|
||||
|
||||
std::vector<PatchArrayVector> _fvarPatchArrays;
|
||||
std::vector<id<MTLBuffer>> _fvarIndexBuffers;
|
||||
std::vector<id<MTLBuffer>> _fvarParamBuffers;
|
||||
};
|
||||
} // end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} //end namespace OpenSubdiv
|
||||
|
||||
#endif //end OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
141
opensubdiv/osd/mtlPatchTable.mm
Normal file
141
opensubdiv/osd/mtlPatchTable.mm
Normal file
@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#import "../osd/mtlPatchTable.h"
|
||||
#import <Metal/Metal.h>
|
||||
#import "../far/patchTable.h"
|
||||
#import "../osd/cpuPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
namespace Osd {
|
||||
|
||||
MTLPatchTable::MTLPatchTable()
|
||||
:
|
||||
_indexBuffer(nil),
|
||||
_patchParamBuffer(nil),
|
||||
_varyingPatchIndexBuffer(nil)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
MTLPatchTable::~MTLPatchTable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static id<MTLBuffer> createBuffer(const void* data, const size_t length,
|
||||
MTLContext* context)
|
||||
{
|
||||
if(length == 0)
|
||||
return nil;
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
|
||||
#elif TARGET_OS_OSX
|
||||
@autoreleasepool {
|
||||
auto cmdBuf = [context->commandQueue commandBuffer];
|
||||
auto blitEncoder = [cmdBuf blitCommandEncoder];
|
||||
|
||||
auto stageBuffer = [context->device newBufferWithBytes:data length:length options:MTLResourceOptionCPUCacheModeDefault];
|
||||
|
||||
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
|
||||
|
||||
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuf commit];
|
||||
[cmdBuf waitUntilCompleted];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[stageBuffer release];
|
||||
#endif
|
||||
|
||||
return finalBuffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MTLPatchTable* MTLPatchTable::Create(const Far::PatchTable *farPatchTable, MTLContext* context)
|
||||
{
|
||||
auto patchTable = new MTLPatchTable();
|
||||
if(patchTable->allocate(farPatchTable, context))
|
||||
return patchTable;
|
||||
|
||||
delete patchTable;
|
||||
assert(0 && "MTLPatchTable Creation Failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MTLPatchTable::allocate(Far::PatchTable const *farPatchTable, MTLContext* context)
|
||||
{
|
||||
CpuPatchTable cpuTable(farPatchTable);
|
||||
|
||||
auto numPatchArrays = cpuTable.GetNumPatchArrays();
|
||||
auto indexSize = cpuTable.GetPatchIndexSize();
|
||||
auto patchParamSize = cpuTable.GetPatchParamSize();
|
||||
|
||||
_patchArrays.assign(cpuTable.GetPatchArrayBuffer(), cpuTable.GetPatchArrayBuffer() + numPatchArrays);
|
||||
|
||||
_indexBuffer = createBuffer(cpuTable.GetPatchIndexBuffer(), indexSize * sizeof(unsigned), context);
|
||||
if(_indexBuffer == nil)
|
||||
return false;
|
||||
|
||||
_indexBuffer.label = @"OSD PatchIndexBuffer";
|
||||
|
||||
_patchParamBuffer = createBuffer(cpuTable.GetPatchParamBuffer(), patchParamSize * sizeof(PatchParam), context);
|
||||
if(_patchParamBuffer == nil)
|
||||
return false;
|
||||
|
||||
_patchParamBuffer.label = @"OSD PatchParamBuffer";
|
||||
|
||||
_varyingPatchArrays.assign(cpuTable.GetVaryingPatchArrayBuffer(), cpuTable.GetVaryingPatchArrayBuffer() + numPatchArrays);
|
||||
|
||||
_varyingPatchIndexBuffer = createBuffer(cpuTable.GetVaryingPatchIndexBuffer(), sizeof(int) * cpuTable.GetVaryingPatchIndexSize(), context);
|
||||
if(_varyingPatchIndexBuffer == nil && cpuTable.GetVaryingPatchIndexSize() > 0)
|
||||
return false;
|
||||
|
||||
auto numFVarChannels = cpuTable.GetNumFVarChannels();
|
||||
_fvarPatchArrays.resize(numFVarChannels);
|
||||
_fvarIndexBuffers.resize(numFVarChannels);
|
||||
_fvarParamBuffers.resize(numFVarChannels);
|
||||
for(auto fvc = 0; fvc < numFVarChannels; fvc++)
|
||||
{
|
||||
_fvarPatchArrays[fvc].assign(cpuTable.GetFVarPatchArrayBuffer(fvc), cpuTable.GetFVarPatchArrayBuffer(fvc) + numPatchArrays);
|
||||
_fvarIndexBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchIndexBuffer(fvc), cpuTable.GetFVarPatchIndexSize(fvc) * sizeof(int), context);
|
||||
if(_fvarIndexBuffers[fvc] == nil)
|
||||
return false;
|
||||
|
||||
_fvarParamBuffers[fvc] = createBuffer(cpuTable.GetFVarPatchParamBuffer(fvc), cpuTable.GetFVarPatchParamSize(fvc) * sizeof(PatchParam), context);
|
||||
if(_fvarParamBuffers[fvc] == nil)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
} //end namespace OpenSubdiv
|
84
opensubdiv/osd/mtlVertexBuffer.h
Normal file
84
opensubdiv/osd/mtlVertexBuffer.h
Normal file
@ -0,0 +1,84 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Osd
|
||||
{
|
||||
class CPUMTLVertexBuffer
|
||||
{
|
||||
public:
|
||||
static CPUMTLVertexBuffer* Create(int numElements, int numVertices, MTLContext* context);
|
||||
|
||||
void UpdateData(const float* src, int startVertex, int numVertices, MTLContext* context);
|
||||
|
||||
int GetNumElements() const
|
||||
{
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int GetNumVertices() const
|
||||
{
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float* BindCpuBuffer();
|
||||
id<MTLBuffer> BindMTLBuffer(MTLContext* context);
|
||||
|
||||
id<MTLBuffer> BindVBO(MTLContext* context)
|
||||
{
|
||||
return BindMTLBuffer(context);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
CPUMTLVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
bool allocate(MTLContext* context);
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
id<MTLBuffer> _buffer;
|
||||
bool _dirty;
|
||||
};
|
||||
|
||||
} //end namespace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} //end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_VERTEX_BUFFER_H
|
98
opensubdiv/osd/mtlVertexBuffer.mm
Normal file
98
opensubdiv/osd/mtlVertexBuffer.mm
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/mtlVertexBuffer.h"
|
||||
#include <Metal/Metal.h>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
namespace OpenSubdiv
|
||||
{
|
||||
namespace OPENSUBDIV_VERSION
|
||||
{
|
||||
namespace Osd
|
||||
{
|
||||
CPUMTLVertexBuffer::CPUMTLVertexBuffer(int numElements, int numVertices)
|
||||
:
|
||||
_numElements(numElements), _numVertices(numVertices),
|
||||
_buffer(nullptr), _dirty(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CPUMTLVertexBuffer::allocate(MTLContext* context)
|
||||
{
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
_buffer = [context->device newBufferWithLength: _numElements * _numVertices * sizeof(float) options:MTLResourceOptionCPUCacheModeDefault];
|
||||
#elif TARGET_OS_OSX
|
||||
_buffer = [context->device newBufferWithLength: _numElements * _numVertices * sizeof(float) options:MTLResourceStorageModeManaged];
|
||||
#endif
|
||||
if(_buffer == nil)
|
||||
return false;
|
||||
|
||||
_dirty = true;
|
||||
_buffer.label = @"OSD VertexBuffer";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CPUMTLVertexBuffer* CPUMTLVertexBuffer::Create(int numElements, int numVertices, MTLContext* context)
|
||||
{
|
||||
auto instance = new CPUMTLVertexBuffer(numElements, numVertices);
|
||||
if(!instance->allocate(context))
|
||||
{
|
||||
delete instance;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void CPUMTLVertexBuffer::UpdateData(const float* src, int startVertex, int numVertices, MTLContext* context)
|
||||
{
|
||||
_dirty = true;
|
||||
memcpy(((float*)_buffer.contents) + startVertex * _numElements, src, _numElements * numVertices * sizeof(float));
|
||||
}
|
||||
|
||||
float* CPUMTLVertexBuffer::BindCpuBuffer()
|
||||
{
|
||||
_dirty = true;
|
||||
return (float*)_buffer.contents;
|
||||
}
|
||||
|
||||
id<MTLBuffer> CPUMTLVertexBuffer::BindMTLBuffer(MTLContext* context)
|
||||
{
|
||||
#if TARGET_OS_OSX
|
||||
if(_dirty)
|
||||
[_buffer didModifyRange:NSMakeRange(0, _buffer.length)];
|
||||
_dirty = false;
|
||||
#endif
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //end namepsace Osd
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
} //end namespace OpenSubdiv
|
@ -33,6 +33,7 @@
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_OUT out
|
||||
#define OSD_INOUT inout
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
elementType[](a0,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
@ -46,6 +47,7 @@
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_OUT out
|
||||
#define OSD_INOUT inout
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7}
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
@ -59,6 +61,7 @@
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_OUT
|
||||
#define OSD_INOUT
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7}
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
@ -72,6 +75,21 @@
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_OUT
|
||||
#define OSD_INOUT
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7}
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11}
|
||||
|
||||
#elif defined(OSD_PATCH_BASIS_METAL)
|
||||
|
||||
#define OSD_FUNCTION_STORAGE_CLASS
|
||||
#define OSD_DATA_STORAGE_CLASS
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_OUT
|
||||
#define OSD_INOUT
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) thread elementType* identifier
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7}
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
@ -85,6 +103,7 @@
|
||||
#define OSD_OPTIONAL_INIT(a,b) (a ? b : 0)
|
||||
#define OSD_OUT
|
||||
#define OSD_INOUT
|
||||
#define OSD_TYPE_ARRAY(elementType, identifier, arraySize) elementType identifier[arraySize]
|
||||
#define OSD_ARRAY_8(elementType,a0,a1,a2,a3,a4,a5,a6,a7) \
|
||||
{a0,a1,a2,a3,a4,a5,a6,a7}
|
||||
#define OSD_ARRAY_12(elementType,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) \
|
||||
@ -95,7 +114,7 @@
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void
|
||||
OsdGetBezierWeights(
|
||||
float t, OSD_OUT float wP[4], OSD_OUT float wDP[4], OSD_OUT float wDP2[4]) {
|
||||
float t, OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP2, 4)) {
|
||||
|
||||
// The four uniform cubic Bezier basis functions (in terms of t and its
|
||||
// complement tC) evaluated at t:
|
||||
@ -128,7 +147,7 @@ OsdGetBezierWeights(
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void
|
||||
OsdGetBSplineWeights(
|
||||
float t, OSD_OUT float wP[4], OSD_OUT float wDP[4], OSD_OUT float wDP2[4]) {
|
||||
float t, OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDP2, 4)) {
|
||||
|
||||
// The four uniform cubic B-Spline basis functions evaluated at t:
|
||||
const float one6th = 1.0f / 6.0f;
|
||||
@ -160,7 +179,7 @@ OsdGetBSplineWeights(
|
||||
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void
|
||||
OsdGetBoxSplineWeights(float v, float w, OSD_OUT float wP[12]) {
|
||||
OsdGetBoxSplineWeights(float v, float w, OSD_TYPE_ARRAY(OSD_OUT float, wP, 12)) {
|
||||
|
||||
float u = 1.0f - v - w;
|
||||
|
||||
@ -215,8 +234,8 @@ OSD_FUNCTION_STORAGE_CLASS
|
||||
void
|
||||
OsdGetBilinearPatchWeights(
|
||||
float s, float t, float dScale,
|
||||
OSD_OUT float wP[4], OSD_OUT float wDs[4], OSD_OUT float wDt[4],
|
||||
OSD_OUT float wDss[4], OSD_OUT float wDst[4], OSD_OUT float wDtt[4]) {
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wP, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 4),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 4), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 4)) {
|
||||
|
||||
float sC = 1.0f - s,
|
||||
tC = 1.0f - t;
|
||||
@ -259,7 +278,7 @@ OsdGetBilinearPatchWeights(
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void OsdAdjustBoundaryWeights(
|
||||
int boundary,
|
||||
OSD_INOUT float sWeights[4], OSD_INOUT float tWeights[4]) {
|
||||
OSD_TYPE_ARRAY(OSD_INOUT float, sWeights, 4), OSD_TYPE_ARRAY(OSD_INOUT float, tWeights, 4)) {
|
||||
|
||||
if ((boundary & 1) != 0) {
|
||||
tWeights[2] -= tWeights[0];
|
||||
@ -285,11 +304,11 @@ void OsdAdjustBoundaryWeights(
|
||||
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void OsdComputeTensorProductPatchWeights(float dScale, int boundary,
|
||||
float sWeights[4], float tWeights[4],
|
||||
float dsWeights[4], float dtWeights[4],
|
||||
float dssWeights[4], float dttWeights[4],
|
||||
OSD_OUT float wP[16], OSD_OUT float wDs[16], OSD_OUT float wDt[16],
|
||||
OSD_OUT float wDss[16], OSD_OUT float wDst[16], OSD_OUT float wDtt[16]) {
|
||||
OSD_TYPE_ARRAY(float, sWeights, 4), OSD_TYPE_ARRAY(float, tWeights, 4),
|
||||
OSD_TYPE_ARRAY(float, dsWeights, 4), OSD_TYPE_ARRAY(float, dtWeights, 4),
|
||||
OSD_TYPE_ARRAY(float, dssWeights, 4), OSD_TYPE_ARRAY(float, dttWeights, 4),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 16),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 16)) {
|
||||
|
||||
if (OSD_OPTIONAL(wP)) {
|
||||
// Compute the tensor product weight of the (s,t) basis function
|
||||
@ -338,8 +357,8 @@ void OsdComputeTensorProductPatchWeights(float dScale, int boundary,
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void OsdGetBezierPatchWeights(
|
||||
float s, float t, float dScale,
|
||||
OSD_OUT float wP[16], OSD_OUT float wDS[16], OSD_OUT float wDT[16],
|
||||
OSD_OUT float wDSS[16], OSD_OUT float wDST[16], OSD_OUT float wDTT[16]) {
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDS, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDT, 16),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wDSS, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDST, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDTT, 16)) {
|
||||
|
||||
float sWeights[4], tWeights[4], dsWeights[4], dtWeights[4], dssWeights[4], dttWeights[4];
|
||||
|
||||
@ -352,8 +371,8 @@ void OsdGetBezierPatchWeights(
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void OsdGetBSplinePatchWeights(
|
||||
float s, float t, float dScale, int boundary,
|
||||
OSD_OUT float wP[16], OSD_OUT float wDs[16], OSD_OUT float wDt[16],
|
||||
OSD_OUT float wDss[16], OSD_OUT float wDst[16], OSD_OUT float wDtt[16]) {
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wP, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 16),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 16), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 16)) {
|
||||
|
||||
float sWeights[4], tWeights[4], dsWeights[4], dtWeights[4], dssWeights[4], dttWeights[4];
|
||||
|
||||
@ -366,8 +385,8 @@ void OsdGetBSplinePatchWeights(
|
||||
OSD_FUNCTION_STORAGE_CLASS
|
||||
void OsdGetGregoryPatchWeights(
|
||||
float s, float t, float dScale,
|
||||
OSD_OUT float wP[20], OSD_OUT float wDs[20], OSD_OUT float wDt[20],
|
||||
OSD_OUT float wDss[20], OSD_OUT float wDst[20], OSD_OUT float wDtt[20]) {
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wP, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDs, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDt, 20),
|
||||
OSD_TYPE_ARRAY(OSD_OUT float, wDss, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDst, 20), OSD_TYPE_ARRAY(OSD_OUT float, wDtt, 20)) {
|
||||
|
||||
//
|
||||
// P3 e3- e2+ P2
|
||||
|
@ -22,8 +22,15 @@
|
||||
# language governing permissions and limitations under the Apache License.
|
||||
#
|
||||
|
||||
_add_executable(stringify "opensubdiv/tools"
|
||||
main.cpp
|
||||
)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set(STRINGIFY_LOCATION "STRINGIFY-NOTFOUND" CACHE FILEPATH "Point it to the stringify binary from a native build")
|
||||
add_executable(stringify IMPORTED GLOBAL)
|
||||
set_property(TARGET stringify PROPERTY IMPORTED_LOCATION ${STRINGIFY_LOCATION})
|
||||
endif()
|
||||
|
||||
install(TARGETS stringify DESTINATION ${CMAKE_BINDIR_BASE})
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
_add_executable(stringify "opensubdiv/tools"
|
||||
main.cpp
|
||||
)
|
||||
install(TARGETS stringify DESTINATION ${CMAKE_BINDIR_BASE})
|
||||
endif()
|
||||
|
Loading…
Reference in New Issue
Block a user