2016-06-29 31 views
1

我想在elm-webgl中製作一個簡單的OpenGL程序。我拿了一個有旋轉框的例子,我想用模板測試來一次渲染一行像素。elm-webgl中的模板緩衝

我能夠實現繪製我想要的線,我試圖設置它只渲染模板緩衝區。然後,我設置了多維數據集的渲染,只通過模板測試(如果模板緩衝區中的行),但似乎不起作用。它只是像正常渲染立方體。

這裏是我的榆樹計劃(的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); 
} 

|] 

我使用的是榆樹的WebGL的修改版本,增加了一些函數調用像ColorMaskStencilMask。這些與他們的JavaScript WebGL計數器部分一對一映射。

我對模具緩衝區的工作方式沒有超級教育,而且我對OpenGL也沒有什麼經驗。我已經閱讀了關於模板緩衝區的兩個教程:this onethis one,據我所知,沒有理由不應該工作。

任何幫助表示讚賞。謝謝!

+1

只是檢查,但你問過一個模板緩衝區? WebGL默認爲*不*有一個。在創建webgl上下文時,您可以通過在JavaScript中將'{stencil:true}'作爲第二個參數傳遞給'getContext'來請求它。我不知道榆樹。 – gman

+0

這絕對是什麼,謝謝!把這作爲答案,我會標記它。 – EmptyFlash

回答

1

只是檢查,但你問過模板緩衝? WebGL默認沒有一個。在創建webgl上下文時,您可以通過在JavaScript中將{stencil: true}作爲第二個參數傳遞給getContext來請求一個。