coordinate_systems.asm

src/1.getting_started/6.1.coordinate_systems/coordinate_systems.asm · 168 lines

;---------------------------------------------------------------------------------------------------
; 6.1 Coordinate systems
;---------------------------------------------------------------------------------------------------
; Three matrices take a vertex from the cube it belongs to all the way to the screen:
;
;   model       the cube's own space -> the world      (where this cube is)
;   view        the world -> the camera's space        (where the eye is)
;   projection  the camera's space -> clip space       (the lens: perspective)
;
;   clip = projection * view * model * position
;
; Ten cubes share one vertex buffer and differ only in their model matrix. A depth buffer, cleared
; every frame, keeps the nearest surface at each pixel so the cubes hide each other correctly.
; D3D's depth runs 0..1 where GL's runs -1..1, which is why m4_perspective differs from glm's in
; two entries.
;
; The cube's vertices are in includes/learn/cube.asm, where every later lesson finds them too.
include rt.inc
include d3d11.inc
include macros.asm
include math.asm
include learn\window.asm
include learn\shader.asm
include learn\gpu.asm
include learn\cube.asm

;---------------------------------------------------------------------------------------------------
.data
;---------------------------------------------------------------------------------------------------
align 4
view_offset vec3 <0.0, 0.0, -3.0>

; Mirrors `cbuffer object` in the shader.
object_constants struct
    model mat4 <>
    view mat4 <>
    projection mat4 <>
object_constants ends

align 16
c object_constants <>
translation mat4 <>
rotation mat4 <>
s shader <>
align 8
cube_vb qword 0
sampler qword 0
constants qword 0
textures qword 2 dup(0)
stride dword cube_stride
offset_ dword 0
current_frame real4 0.0

;---------------------------------------------------------------------------------------------------
.code
;---------------------------------------------------------------------------------------------------
align 16
main proc
    USING rbx
    SaveRegs
    invoke window_create, "LearnD3D11"
    ; A depth buffer the size of the window: 24 bits of depth, 8 of stencil (window.asm).
    call window_create_depth

    invoke create_sampler, D3D11_FILTER_ANISOTROPIC, D3D11_TEXTURE_ADDRESS_WRAP
    mov sampler, rax
    vcall context, ID3D11DeviceContext_PSSetSamplers, 0, 1, ADDR sampler

    ; build and compile our shader program
    ; ------------------------------------
    invoke shader_create, ADDR s, "src/1.getting_started/6.1.coordinate_systems/coordinate_systems.hlsl", ADDR cube_layout, cube_layout_count

    ; set up vertex data and textures
    ; -------------------------------
    invoke create_buffer, D3D11_BIND_VERTEX_BUFFER, ADDR cube_vertices, cube_vertices_size
    mov cube_vb, rax
    invoke filesystem_path, "resources/textures/container.jpg"
    invoke load_texture, rax, 0
    mov textures[0], rax
    invoke filesystem_path, "resources/textures/awesomeface.png"
    invoke load_texture, rax, 0
    mov textures[8], rax
    invoke create_constant_buffer, sizeof object_constants
    mov constants, rax

    ; render loop
    ; -----------
    render_loop:
        call window_poll
        test eax, eax
        jz render_loop_done

        ; per-frame time logic
        ; --------------------
        call get_time
        movss current_frame, xmm0

        ; render
        ; ------
        vcall context, ID3D11DeviceContext_OMSetRenderTargets, 1, ADDR backbuffer_rtv, depth_dsv
        vcall context, ID3D11DeviceContext_RSSetViewports, 1, ADDR viewport
        vcall context, ID3D11DeviceContext_ClearRenderTargetView, backbuffer_rtv, floats(0.2, 0.3, 0.3, 1.0)
        ; The depth to clear to is a float: the fourth argument, counting `this`, so it travels in
        ; xmm3, and the 0 in its place on the vcall line is only a placeholder.
        movf xmm3, 1.0
        vcall context, ID3D11DeviceContext_ClearDepthStencilView, depth_dsv, D3D11_CLEAR_DEPTH or D3D11_CLEAR_STENCIL, 0, 0

        vcall context, ID3D11DeviceContext_PSSetShaderResources, 0, 2, ADDR textures
        invoke shader_use, ADDR s
        invoke bind_constants, 0, constants
        vcall context, ID3D11DeviceContext_IASetPrimitiveTopology, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
        vcall context, ID3D11DeviceContext_IASetVertexBuffers, 0, 1, ADDR cube_vb, ADDR stride, ADDR offset_

        ; view = translate(0, 0, -3): the world moves away from the eye
        invoke m4_translate, ADDR c.view, ADDR view_offset
        ; projection = perspective(45 degrees, width / height, 0.1, 100)
        movf xmm0, 100.0
        movss real4 ptr [rsp + 32], xmm0        ; z_far, the fifth argument, on the stack
        movf xmm0, 45.0
        call radians
        movaps xmm1, xmm0                       ; fovy
        cvtsi2ss xmm2, scr_width
        cvtsi2ss xmm0, scr_height
        divss xmm2, xmm0                        ; aspect
        movf xmm3, 0.1                          ; z_near
        lea rcx, c.projection
        call m4_perspective

        xor ebx, ebx
        cubes:
            ; angle = radians(20 * i), and every third cube spins with time
            cvtsi2ss xmm0, ebx
            movf xmm1, 20.0
            mulss xmm0, xmm1
            call radians
            mov eax, ebx
            xor edx, edx
            mov ecx, 3
            div ecx
            test edx, edx
            jnz still
                addss xmm0, current_frame
            still:
            ; model = translate(cube_positions[i]) * rotate(angle, (1, 0.3, 0.5))
            movaps xmm1, xmm0
            lea rcx, rotation
            lea r8, cube_rotation_axis
            call m4_rotate
            imul eax, ebx, sizeof vec3
            lea rdx, cube_positions
            add rdx, rax
            invoke m4_translate, ADDR translation, rdx
            invoke m4_mul, ADDR c.model, ADDR translation, ADDR rotation
            invoke update_buffer, constants, ADDR c, sizeof object_constants
            vcall context, ID3D11DeviceContext_Draw, 36, 0
            inc ebx
            cmp ebx, 10
            jb cubes

        call window_present
        jmp render_loop
    render_loop_done:

    RestoreRegs
    invoke ExitProcess, 0
main endp

end
Part of masm64-dx11, LearnOpenGL's lessons rewritten for Direct3D 11 in x64 assembly. Licensed CC BY-NC 4.0, after LearnOpenGL by Joey de Vries.