Introduction

This site walks through modern real-time rendering one small program at a time, from an empty window to image based physically based rendering. It is LearnOpenGL, the tutorial series by Joey de Vries, retold for Direct3D 11 on Windows and written in x64 assembly: Microsoft's assembler, ml64, with the macros of the MASM64 SDK. The chapters keep LearnOpenGL's order, its structure and much of its route through each subject, because that route works. The prose is rewritten, every program is new, and wherever Direct3D does something differently from OpenGL, or assembly does something differently from C, the chapter stops to say so.

The backpack model Shadow mapping
Bloom Image based lighting with textured materials

It has a twin: Learn D3D11 in rin tells the same story in a small C-like language, and the programs here follow those lesson for lesson, down to the shaders, which are shared unchanged. If you already know LearnOpenGL, you can read this as a translation guide: every chapter links its original, and the maths and techniques carry over unchanged. If you don't, you can read it on its own; nothing here assumes you have seen OpenGL.

Prerequisites

Direct3D is an API, not a language, so we need one to call it from. Ours is assembly, with no C runtime underneath: the window is Win32, images are decoded by Windows' own codecs, shaders are compiled by D3DCompile, and everything else, the maths, the model reader, the image formats, is written out in the lessons and their includes. It helps to have read some x86-64 before; masm64-init is a gentle start. What these programs lean on most is explained where it first shows up, chiefly these:

Direct3D's own interfaces are COM objects: a pointer to a table of functions, called with the object as the hidden first argument. The next chapter says more, and the repository's notes on the assembly collect every convention and trap in one place.

We also use some mathematics along the way: vectors, matrices, a little trigonometry, and for PBR a few integrals. Each is introduced when it is needed and explained as far as the chapter needs it, with pointers to fuller treatments. Here the vector and matrix code is SSE, four floats to a register, which turns out to suit it well.

Structure

The menu on the left lists the chapters in order, grouped into sections, the same sections LearnOpenGL has with "Advanced OpenGL" renamed. Read them top to bottom: each one builds on the program and the ideas of the one before. Every chapter explains the theory first, then builds it up in code, ending with a link to the complete program, some exercises, and further reading.

Each chapter is one standalone program: a single .asm file, assembled on its own, with its HLSL shaders in the same folder. The first two lessons write absolutely everything out; after that, what has been explained once moves into includes/, which play the parts LearnOpenGL gives its libraries (GLFW, GLAD, GLM, stb_image) and its helper headers for shaders, the camera and models. All of the source can be read here in the code viewer, linked from each chapter, or on GitHub.

Where LearnOpenGL splits a lesson into several programs (an indexed triangle next to the plain one, a textured PBR scene next to the plain spheres), ours keeps them in one program and switches between them with Tab or the number keys. The chapter says which key does what.

To keep the text easy to scan, a few conventions are used throughout.

Boxes

Green boxes hold notes: useful details about Direct3D, HLSL, the assembler or the subject at hand, and how it compares with OpenGL. Red boxes hold warnings: things that are easy to get wrong, and that fail quietly when you do.

Code

Code appears in boxes with an amber edge, highlighted, assembly for the programs and HLSL for the shaders. In the assembly, instructions, registers, assembler directives and the project's macros each have their own colour:

; rcx: bind flags, rdx: data, r8: size -> rax: ID3D11Buffer
;
; An immutable buffer: filled once at creation, never written by the CPU again.
align 16
create_buffer proc bind:qword, data:qword, data_size:qword

The snippets are copied from the real programs, so they always match what you will find in the full source. The button at the top right switches the page between light and dark.

Colour hints

Some words are coloured to show what kind of thing they are:

Building the lessons

You will need Windows, Visual Studio with the C++ x64 tools (for ml64 and link), the Windows SDK, and the MASM64 SDK from masm32.com, installed into C:\masm64 or pointed at by MASM64_HOME. With those in place, one script builds all 38 programs, each a single ml64 and a single link:

git clone https://github.com/IbrahimHindawi/masm64-dx11
cd masm64-dx11
scripts\build.bat
build\hello_triangle.exe

Creating a window goes through the setup in detail. Every lesson uses the same controls once there is a camera to move: W, A, S and D with Space and Shift to fly, the right mouse button held down to look around, the mouse wheel to zoom, and Escape to quit.

Credit

The tutorial this follows is Joey de Vries' LearnOpenGL, also available as a book, with its code on GitHub. Its chapters, choice of examples and much of the way each subject is explained come from there, along with the textures, models and HDR environment the lessons load, and the diagrams marked as LearnOpenGL's. LearnOpenGL is licensed CC BY-NC 4.0, and so is everything here. Thank you, Joey: a great many of us learned graphics from your site.

Now that the layout is familiar, head on to Getting started.

Credit: this chapter follows LearnOpenGL's Introduction by Joey de Vries, rewritten for Direct3D 11 and x64 assembly. LearnOpenGL's text and code are licensed CC BY-NC 4.0, and so is this page; the wording, code and screenshots here are new, and diagrams marked as LearnOpenGL's are its own.