【问题标题】:Custom clipping plane with SceneKit使用 SceneKit 自定义剪切平面
【发布时间】:2023-03-04 22:49:01
【问题描述】:

是否可以在使用 SceneKit 时创建自定义剪切平面?由于您可以提供自己的着色器,我唯一需要做的就是以某种方式启用 GL_CLIP_DISTANCE0。这是可能的还是我必须坚持使用较低级别的库?

编辑:

我尝试使用渲染器委托启用 GL 状态 GL_CLIP_DISTANCE0,但没有效果。以下是相关代码部分:

class GameViewController: NSViewController, SCNSceneRendererDelegate {

 @IBOutlet weak var gameView: GameView!

 override func awakeFromNib() {
   let attrs: [Int] = [
     NSOpenGLPFADoubleBuffer,
     NSOpenGLPFADepthSize, 24,
     NSOpenGLPFAOpenGLProfile,
     NSOpenGLProfileVersion3_2Core,
     0
   ]

   let pixelFormat: NSOpenGLPixelFormat = NSOpenGLPixelFormat(attributes: UnsafePointer<NSOpenGLPixelFormatAttribute>(attrs))

   gameView.pixelFormat = pixelFormat

   let scene = SCNScene()      
   let obj = SCNSphere(radius: 1.0)
   obj.shaderModifiers = [SCNShaderModifierEntryPointGeometry: "gl_CLipDistance[0] = 0.0;"]
   let objNode = SCNNode(geometry: obj)
   scene.rootNode.addChildNode(objNode)

   // ... create camera and lights ...

   // set renderer delegate
   self.gameView.delegate = self

   // set the scene to the view
   self.gameView!.scene = scene      
   self.gameView!.backgroundColor = NSColor.blackColor()
 }

 func renderer(aRenderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
  glEnable(GLenum(GL_CLIP_DISTANCE0))
 }
}

无论我尝试什么,我都会收到以下错误:

SceneKit: error,   2: uniform mat4 u_normalTransform;
SceneKit: error,   3: uniform mat4 u_projectionTransform;
SceneKit: error,   4: uniform mat4 u_modelViewTransform;
SceneKit: error,   5: // In model space, must stay in it
SceneKit: error,   6: struct SCNShaderGeometry
SceneKit: error,   7: {
SceneKit: error,   8:   vec4 position;
SceneKit: error,   9:   vec3 normal;
SceneKit: error,  10:   vec4 tangent;
SceneKit: error,  11:   vec4 color;
SceneKit: error,  12:   vec2 texcoords[8]; // MAX_UV
SceneKit: error,  13: } _geometry;
SceneKit: error,  14: struct SCNShaderSurface
SceneKit: error,  15: {
SceneKit: error,  16:   vec3 view; // in view space
SceneKit: error,  17:   vec3 position; // in view space
SceneKit: error,  18:   vec3 normal; // in view space
SceneKit: error,  19:   vec3 tangent; // in view space
SceneKit: error,  20:   vec3 bitangent; // in view space
SceneKit: error,  21:   float shininess;
SceneKit: error,  22:   float fresnel;
SceneKit: error,  23:   vec3 _normalTS; // UNDOCUMENTED in tangent space
SceneKit: error,  24:   vec4 diffuse;
SceneKit: error,  25: } _surface;
SceneKit: error,  26: // Attributes
SceneKit: error,  27: attribute vec4 a_position;
SceneKit: error,  28: attribute vec3 a_normal;
SceneKit: error,  29: // Varyings
SceneKit: error,  30: varying vec3 v_position;
SceneKit: error,  31: varying vec3 v_normal;
SceneKit: error,  32: void main(void)
SceneKit: error,  33: {
SceneKit: error,  34:   _geometry.position = a_position;
SceneKit: error,  35:   _geometry.normal = a_normal;
SceneKit: error,  36:   gl_CLipDistance[0] = 0.0;
SceneKit: error,  37:   // Transform the geometry elements in view space
SceneKit: error,  38:   _surface.position = (u_modelViewTransform * _geometry.position).xyz;
SceneKit: error,  39:   _surface.normal = normalize(mat3(u_normalTransform) * _geometry.normal);
SceneKit: error,  40:   //if USE_VIEW is 2 we may also need to set _surface.view. todo: make USE_VIEW a mask
SceneKit: error,  41:   v_position = _surface.position;
SceneKit: error,  42:   v_normal = _surface.normal;
SceneKit: error,  43:     
SceneKit: error,  44:   // this means that the geometry are still in model space
SceneKit: error,  45:   gl_Position = u_projectionTransform * vec4(_surface.position, 1.);
SceneKit: error,  46: }
SceneKit: error,  47: 
SceneKit: error, failed to link program: ERROR: 0:36: Use of undeclared identifier 'gl_CLipDistance'

是我做错了什么还是“gl_ClipDistance”在 SceneKit 使用的 OpenGL 版本中根本不可用?

【问题讨论】:

  • 您的着色器错误是因为您将gl_clipDistance 大写错误。
  • 不幸的是,这不是问题所在。不同的大小写不会改变错误。另外,在OpenGL docs 中,它像我一样大写。
  • @UliHeld:不,不是。您用大写 L 拼写。
  • 你是对的!感谢您的关注。不幸的是,它仍然无法正常工作。与此同时,我发现自定义剪辑存在许多兼容性问题。也许使用截锥体进行剪辑更容易。

标签: opengl scenekit


【解决方案1】:

如果您想在 SceneKit 渲染场景之前启用某些 GL 状态,请使用 scene renderer delegate。在renderer:willRenderScene:atTime: 方法中,您可以glEnable 自定义着色器所依赖的任何状态。

【讨论】:

  • 感谢您的建议!不幸的是,这对我不起作用。我用代码示例扩展了我的问题。
【解决方案2】:

在 SceneKit 中集成自定义 OpenGL 代码的三种方式:

(1) node.renderDelegate 但这仅适用于指定的节点。
(2) SCNPrograms 附在资料上。
(3) 自己的渲染器

您在 (1) 或 (3) 中启用的状态适用于 (2) 中的任何程序,因此在这种情况下选择一个或另一个更多地取决于自定义剪辑是否应应用于特定节点(使用选项 1 ),或所有节点(使用选项 3)。

对于 (3),请参阅 https://developer.apple.com/reference/scenekit/scnscenerendererdelegate,其中包含 SCNSceneRendererDelegate 中的所有委托方法以及对 SCNNodeRendererDelegate 和 SCNShadable 的引用。

【讨论】:

  • 如果我错了,请纠正我,但选项 (1) 使用需要自定义渲染器的 SCNNodeRendererDelegate。据我所知,这意味着除了为特定节点或整个场景编写自定义渲染器之外别无他法。
猜你喜欢
  • 2011-07-31
  • 2021-10-25
  • 1970-01-01
  • 2023-04-11
  • 2019-02-12
  • 2018-12-26
  • 1970-01-01
  • 2019-06-01
  • 2022-01-23
相关资源
最近更新 更多