javascript - elm-webgl 中的模板缓冲

标签 javascript webgl shader elm

我正在尝试在 elm-webgl 中制作一个简单的 OpenGL 程序。我举了一个例子,它有一个可以旋转的盒子,我想使用模板测试一次只渲染一行像素。

我能够绘制我想要的线条,并且我尝试将其设置为仅在模板缓冲区上渲染。然后,我将立方体的渲染设置为仅通过模板缓冲区中的行的模板测试,但它似乎不起作用。它只是像平常一样渲染立方体。

这是我的 Elm 程序(this example 的修改版本):

import Math.Vector2 exposing (Vec2)
import Math.Vector3 exposing (..)
import Math.Matrix4 exposing (..)
import Task
import Time exposing (Time)
import WebGL exposing (..)
import WebGL exposing (FunctionCall(..), CompareMode(..), Capability(..), ZMode(..))
import Html exposing (Html)
import Html.App as Html
import AnimationFrame
import Html.Attributes exposing (width, height)


type alias Model =
  { texture : Maybe Texture
  , theta : Float
  }


type Action
  = TextureError Error
  | TextureLoaded Texture
  | Animate Time


update : Action -> Model -> (Model, Cmd Action)
update action model =
  case action of
    TextureError err ->
      (model, Cmd.none)
    TextureLoaded texture ->
      ({model | texture = Just texture}, Cmd.none)
    Animate dt ->
      ({model | theta = model.theta + dt / 10000}, Cmd.none)


init : (Model, Cmd Action)
init =
  ( {texture = Nothing, theta = 0}
  , loadTexture "/woodCrate.jpg"
    |> Task.perform TextureError TextureLoaded
  )


main : Program Never
main =
  Html.program
    { init = init
    , view = view
    , subscriptions = (\model -> AnimationFrame.diffs Animate)
    , update = update
    }


-- MESHES

crate : Drawable { pos:Vec3, coord:Vec3 }
crate =
  Triangle <|
  List.concatMap rotatedFace [ (0,0), (90,0), (180,0), (270,0), (0,90), (0,-90) ]


fmod : Float -> Float -> Float
fmod a b =
  a - (toFloat <| floor <| a / b) * b


line : Float -> Drawable { pos: Vec3 }
line theta =
  let
    y = (fmod -theta 2) - 1
  in
    Lines
      [ ({ pos = vec3 -1 y 0 } , { pos = vec3 1 y 0 })
      ]


rotatedFace : (Float,Float) -> List ({ pos:Vec3, coord:Vec3 }, { pos:Vec3, coord:Vec3 }, { pos:Vec3, coord:Vec3 })
rotatedFace (angleX,angleY) =
  let
    x = makeRotate (degrees angleX) (vec3 1 0 0)
    y = makeRotate (degrees angleY) (vec3 0 1 0)
    t = x `mul` y `mul` makeTranslate (vec3 0 0 1)
    each f (a,b,c) =
      (f a, f b, f c)
  in
    List.map (each (\x -> {x | pos = transform t x.pos })) face


face : List ({ pos:Vec3, coord:Vec3 }, { pos:Vec3, coord:Vec3 }, { pos:Vec3, coord:Vec3 })
face =
  let
    topLeft     = { pos = vec3 -1  1 0, coord = vec3 0 1 0 }
    topRight    = { pos = vec3  1  1 0, coord = vec3 1 1 0 }
    bottomLeft  = { pos = vec3 -1 -1 0, coord = vec3 0 0 0 }
    bottomRight = { pos = vec3  1 -1 0, coord = vec3 1 0 0 }
  in
    [ (topLeft,topRight,bottomLeft)
    , (bottomLeft,topRight,bottomRight)
    ]


-- VIEW

perspective : Float -> Mat4
perspective angle =
  List.foldr mul Math.Matrix4.identity
    [ perspectiveMatrix
    , camera
    , makeRotate (3*angle) (vec3 0 1 0)
    , makeRotate (2*angle) (vec3 1 0 0)
    ]

perspectiveMatrix : Mat4
perspectiveMatrix =
  makePerspective 45 1 0.01 100


camera : Mat4
camera =
  makeLookAt (vec3 0 0 5) (vec3 0 0 0) (vec3 0 1 0)

lineFunctionCalls: List FunctionCall
lineFunctionCalls =
  [ Disable StencilTest
  , Enable StencilTest
  , StencilFunc (Always, 1, 0xFF)
  , StencilMask 0xFF
  , DepthMask 0x00
  , ColorMask (0x00, 0x00, 0x00, 0x00)
  ]

cubeFunctionCalls: List FunctionCall
cubeFunctionCalls =
  [ StencilFunc (Equal, 1, 0xFF)
  , StencilMask 0x00
  , DepthMask 0xFF
  , ColorMask (0xFF, 0xFF, 0xFF, 0xFF)
  ]

initFunctionCalls: List FunctionCall
initFunctionCalls =
  [ Enable DepthTest
  , DepthFunc Less
  ]

view : Model -> Html Action
view {texture, theta} =
  (case texture of
    Nothing ->
        []
    Just tex ->
        [ renderWithConfig lineFunctionCalls lineVertexShader lineFragmentShader (line theta) {}
        , renderWithConfig cubeFunctionCalls vertexShader fragmentShader crate { crate = tex, perspective = perspective theta }
        ]
  )
  |> WebGL.toHtmlWith initFunctionCalls [width 400, height 400]


-- SHADERS

vertexShader : Shader { pos:Vec3, coord:Vec3 } { u | perspective:Mat4 } { vcoord:Vec2 }
vertexShader = [glsl|

attribute vec3 pos;
attribute vec3 coord;
uniform mat4 perspective;
varying vec2 vcoord;

void main () {
  gl_Position = perspective * vec4(pos, 1.0);
  vcoord = coord.xy;
}

|]

lineVertexShader : Shader { pos: Vec3 } u {}
lineVertexShader = [glsl|
attribute vec3 pos;

void main() {
  gl_Position = vec4(pos, 1.0);
}
|]

lineFragmentShader : Shader a u {}
lineFragmentShader = [glsl|
precision mediump float;

void main() {
  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
|]


fragmentShader : Shader {} { u | crate:Texture } { vcoord:Vec2 }
fragmentShader = [glsl|

precision mediump float;
uniform sampler2D crate;
varying vec2 vcoord;

void main () {
  gl_FragColor = texture2D(crate, vcoord);
}

|]

我使用的是 elm-webgl 的修改版本,它添加了几个函数调用,例如 ColorMaskStencilMask。它们与其 JavaScript WebGL 对应部分一一对应。

我对模板缓冲区的工作原理了解不多,而且对 OpenGL 也没什么经验。我读过两篇关于模板缓冲区的教程:this onethis one ,据我所知,没有理由这不起作用。

感谢任何帮助。谢谢!

最佳答案

只是检查一下,但您是否要求模板缓冲区? WebGL 默认情况下没有。您可以在创建 webgl 上下文时通过将 {stencil: true} 作为第二个参数传递给 JavaScript 中的 getContext 来请求一个。

关于javascript - elm-webgl 中的模板缓冲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38110650/

相关文章:

javascript - 如何获取外部 URL 的计算 CSS?

javascript - IE 不将 url 参数传递给 js 脚本吗?

glsl - 从 Shadershop 函数到 glsl 函数的问题

c - OpenGL glAttachShader 不工作

javascript - 使用 gsub 从源代码中删除 javascript 控制台语句

javascript - 修复 AWS API 网关和放大中不存在的 CORS "Response to preflight..." header

javascript - WebGL - 顶点着色器调用的变量数组大小

javascript - WebGL 片段着色器不透明度

ios - UIWebView HTML 5 游戏 Canvas 在 iOS 9 中绘制缓慢,或 WebGL 在 iOS 8.0 及更高版本中崩溃

Opengl 简单片段着色器在纹理上叠加半透明三角形带