Hello Cube Vulkan MASM x64

Тема в разделе "Vulkan", создана пользователем ml64, 29 июн 2026.

  1. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    60
    Это развитие темы "Рамочное приложение Vulkan на MASM x64"
    Здесь будем крутить и двигать простой куб, грани которого окрашены в цвета кубика Рубика для наглядности.
    Вулкана здесь будет меньше, зато больше GLSL, векторов, матриц и кватернионов.
    В отличие от темы "Рамочное приложение Vulkan на MASM x64" здесь во главе угла будет не механика Вулкана, а геометрия.
    Но, поскольку Вулкан - масштабируемая платформа, здесь будем включать и выключать различные его функции.

    Понеслась. Идём в 3D, а для этого добавляем буфер глубины


    Если до этого Вулкан отрисовывал полигоны в том порядке, в котором он их обрабатывал, то теперь он будет учитывать расстояние, на которое удалены точки.
    Это необходимое условие работы в 3D, иначе будет вот так:
    Clipped.jpg

    Код (ASM):
    1.  
    2. createDepthImage proc
    3. LOCAL index:DWORD
    4. PROLOG 100h
    5.  
    6. ;1. Fill VkImageCreateInfo
    7. mov eax,chosenExtent_width
    8. mov imageInfo_extent_width,eax
    9. mov eax,chosenExtent_height
    10. mov imageInfo_extent_height,eax
    11.  
    12. ;2. Create Depth Image
    13. LOG_TEXT szVkCreateImage
    14. mov rcx,ghVkLogicalDevice
    15. lea rdx,imageInfo_sType
    16. xor r8,r8
    17. lea r9,ghVkDepthImage
    18. call vkCreateImage
    19. test rax,rax
    20. jnz lbl_VkError
    21. cmp ghVkDepthImage,0
    22. je lbl_VkError
    23. mov rax,ghVkDepthImage
    24. mov depthViewInfo_image,rax
    25. LOG_TEXT szOK
    26.  
    27. ;3. Get Image Memory Requirements
    28. LOG_TEXT szVkGetImageMemoryRequirements
    29. mov rcx,ghVkLogicalDevice
    30. mov rdx,ghVkDepthImage
    31. lea r8,memReqs_size ;address of VkMemoryRequirements structure
    32. call vkGetImageMemoryRequirements
    33. cmp memReqs_size,0
    34. je lbl_Error_NoImgMemReqs
    35. cmp memReqs_alignment,0
    36. je lbl_Error_NoImgMemReqs
    37. LOG_TEXT szOK
    38.  
    39. ;4. Find memory type index
    40. LOG_TEXT szVkGetPhysicalDeviceMemoryProperties
    41. mov rcx,ghVkPhysicalDevice
    42. lea rdx,memProps_memoryTypeCount ;address of VkPhysicalDeviceMemoryProperties
    43. call vkGetPhysicalDeviceMemoryProperties
    44. cmp memProps_memoryTypeCount,0
    45. je lbl_Error_NoDeviceMemory
    46. LOG_TEXT szOK
    47.  
    48. ;5. Loop through memory types
    49. xor rcx,rcx ;i = 0
    50. mov index,ecx
    51.  
    52. ;Check if this type supports the required memory type bits
    53. search_memory_type:
    54. mov rax,1
    55. mov ecx,index
    56. shl eax,cl ;1 << index
    57. and eax,memReqs_memoryTypeBits
    58. jz next_memory_type
    59.  
    60. ;Check if it has VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT (0x01)
    61. ;Offset of memoryTypes[i].propertyFlags is i * 8
    62. shl rcx,3 ;i*8
    63. lea rsi,memProps_memoryTypes
    64. add rsi,rcx
    65. test dword ptr[rsi],1 ;check if VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT is set
    66. jnz found_memory_type
    67.  
    68. next_memory_type:
    69. inc index
    70. mov ecx,index
    71. cmp ecx,memProps_memoryTypeCount
    72. jl search_memory_type
    73.  
    74. ;If not found, fallback to any type matching bits (without checking properties)
    75. xor rcx,rcx
    76. mov index,ecx
    77.  
    78. fallback_search:
    79. mov rax,1
    80. mov ecx,index
    81. shl eax,cl ;1 << index
    82. and eax,memReqs_memoryTypeBits
    83. jnz found_memory_type
    84.  
    85. inc index
    86. mov ecx,index
    87. cmp ecx,memProps_memoryTypeCount
    88. jl fallback_search
    89.  
    90. ;If still not found -> error
    91. LOG_TEXT szNoDeviceMemory
    92. jmp lbl_Error_NoDeviceMemory
    93.  
    94. found_memory_type:
    95. mov ecx,index
    96. mov depthAllocInfo_memoryTypeIndex,ecx
    97. LOG_TEXT szDeviceMemoryFound
    98.  
    99. ;6. Align allocation size to the required alignment
    100. mov rax,memReqs_size
    101. mov rbx,memReqs_alignment
    102. cmp rbx,0
    103. je lbl_Error_NoImgMemReqs
    104.  
    105. dec rbx
    106. add rax,rbx
    107. not rbx
    108. and rax,rbx
    109. ; Ensure non-zero
    110. test rax,rax
    111. jz lbl_Error_ZeroSize
    112.  
    113. ;7. Set allocation size from requirements
    114. mov depthAllocInfo_allocationSize,rax
    115.  
    116. ;8. Allocate the Device Memory
    117. LOG_TEXT szVkAllocateMemory
    118. mov rcx,ghVkLogicalDevice
    119. lea rdx,depthAllocInfo_sType ;address of VkMemoryAllocateInfo structure
    120. xor r8,r8 ;pAllocator
    121. lea r9,ghVkDepthDeviceMemory
    122. call vkAllocateMemory
    123. test rax,rax
    124. jnz lbl_VkError
    125. cmp ghVkDepthDeviceMemory,0
    126. je lbl_VkError
    127. LOG_TEXT szOK
    128.  
    129. ;9. Bind the memory to the image
    130. LOG_TEXT szVkBindImageMemory
    131. mov rcx,ghVkLogicalDevice
    132. mov rdx,ghVkDepthImage
    133. mov r8,ghVkDepthDeviceMemory
    134. xor r9,r9 ;memoryOffset = 0
    135. call vkBindImageMemory
    136. test rax,rax
    137. jnz lbl_VkError
    138. LOG_TEXT szOK
    139.  
    140. ;10. Create Depth Image View
    141. LOG_TEXT szVkCreateImageView
    142. mov rcx,ghVkLogicalDevice
    143. lea rdx,depthViewInfo_sType ;Reuse the existing VkImageViewCreateInfo structure
    144. xor r8,r8
    145. lea r9,ghVkDepthImageView
    146. call vkCreateImageView
    147. test rax,rax
    148. jnz lbl_VkError
    149. cmp ghVkDepthImageView,0
    150. je lbl_VkError
    151. LOG_TEXT szOK
    152.  
    153. jmp lbl_End
    154.  
    155. lbl_Error_NoImgMemReqs:
    156. LOG_TEXT szNoImgMemReqs
    157. jmp lbl_End
    158.  
    159. lbl_Error_ZeroSize:
    160. LOG_TEXT szErrorZeroSize
    161. jmp lbl_End
    162.  
    163. lbl_Error_NoDeviceMemory:
    164. LOG_TEXT szNoDeviceMemory
    165. jmp lbl_End
    166.  
    167. lbl_VkError:
    168. call SpellVkError
    169.  
    170. lbl_End:
    171. EPILOG
    172. createDepthImage endp
    173.  

    Создаём куб


    Ранее мы создали загрузчик шейдеров, здесь мы им воспользуемся по полной программе.
    Код (C):
    1. #version 450
    2.  
    3. // OBJECT GEOMETRY
    4.  
    5. // 8 unique cube vertices
    6. const vec3 cubeVerts[8] = {
    7. vec3(-1.0, -1.0, -1.0), // 0
    8. vec3(+1.0, -1.0, -1.0), // 1
    9. vec3(+1.0, +1.0, -1.0), // 2
    10. vec3(-1.0, +1.0, -1.0), // 3
    11. vec3(-1.0, -1.0, +1.0), // 4
    12. vec3(+1.0, -1.0, +1.0), // 5
    13. vec3(+1.0, +1.0, +1.0), // 6
    14. vec3(-1.0, +1.0, +1.0)  // 7
    15. };
    16.  
    17. // Cube vertices (36 vertices, 6 faces, 2 triangles per face)
    18. const vec3 cubeVertices[36] = {
    19. // Face -Z (Bottom) – White
    20. cubeVerts[0], cubeVerts[3], cubeVerts[2],
    21. cubeVerts[0], cubeVerts[2], cubeVerts[1],
    22. // Face -Y (Front) – Blue
    23. cubeVerts[0], cubeVerts[1], cubeVerts[5],
    24. cubeVerts[0], cubeVerts[5], cubeVerts[4],
    25. // Face +X (Right) – Red
    26. cubeVerts[1], cubeVerts[2], cubeVerts[6],
    27. cubeVerts[1], cubeVerts[6], cubeVerts[5],
    28. // Face +Y (Back) – Green
    29. cubeVerts[2], cubeVerts[3], cubeVerts[7],
    30. cubeVerts[2], cubeVerts[7], cubeVerts[6],
    31. // Face -X (Left) – Orange
    32. cubeVerts[0], cubeVerts[4], cubeVerts[7],
    33. cubeVerts[0], cubeVerts[7], cubeVerts[3],
    34. // Face +Z (Top) – Yellow
    35. cubeVerts[4], cubeVerts[5], cubeVerts[6],
    36. cubeVerts[4], cubeVerts[6], cubeVerts[7]
    37. };
    38.  
    39. // OBJECT COLOR
    40.  
    41. // Rubik's cube face colours (matching the order above)
    42. const vec3 faceColors[6] = {
    43. vec3(1.0, 1.0, 1.0), //Face -Z (Bottom) – White
    44. vec3(0.0, 0.0, 1.0), //Face -Y (Front) – Blue
    45. vec3(1.0, 0.0, 0.0), //Face +X (Right) – Red
    46. vec3(0.0, 1.0, 0.0), //Face +Y (Back) – Green
    47. vec3(1.0, 0.5, 0.0), //Face -X (Left) – Orange
    48. vec3(1.0, 1.0, 0.0) //Face +Z (Top) – Yellow
    49. };
    50.  
    51. // PROJECTION TRANSFORMATIONS
    52.  
    53. // 0. Orthographic Projection
    54. float nearPlane = -2.0;
    55. float farPlane  =  10.0;
    56. float o22 = 1.0 / (farPlane - nearPlane);
    57. float o23 = -nearPlane / (farPlane - nearPlane);
    58. float o32 = 0.0;
    59.  
    60. mat4 mtxOrtho = mat4(
    61. vec4(1.0, 0.0, 0.0, 0.0),
    62. vec4(0.0, 1.0, 0.0, 0.0),
    63. vec4(0.0, 0.0, o22, o32),
    64. vec4(0.0, 0.0, o23, 1.0)
    65. );
    66.  
    67. // 0. Perspective Projection
    68. float aspect = 1.0; // 512/512
    69. float fovY = radians(60.0);
    70. float nearZ = 0.1; // Near plane at z_eye = -0.1
    71. float farZ = 10.0; // Far plane at z_eye = -10.0
    72.  
    73. float p11 = -1.0 / tan(fovY * 0.5); // Mirror about XZ plane
    74. float p00 = p11 / aspect;
    75. float p22 = -farZ / (farZ - nearZ);
    76. float p32 = -1.0; // Makes w_clip = -z_eye
    77. float p23 = nearZ * p22;
    78.  
    79. mat4 mtxPersp = mat4(
    80. vec4(p00, 0.0, 0.0, 0.0),
    81. vec4(0.0, p11, 0.0, 0.0),
    82. vec4(0.0, 0.0, p22, p32),
    83. vec4(0.0, 0.0, p23, 0.0)
    84. );
    85.  
    86. // AFFINE TRANSFORMATIONS
    87.  
    88. //0. Translate
    89. float tx = 0.0;
    90. float ty = 0.0;
    91. float tz = -4.0;
    92. mat4 transMat = mat4(
    93. vec4(1.0, 0.0, 0.0, 0.0),
    94. vec4(0.0, 1.0, 0.0, 0.0),
    95. vec4(0.0, 0.0, 1.0, 0.0),
    96. vec4( tx,  ty, tz, 1.0)
    97. );
    98.  
    99. // 1. Overall Scale
    100. float S = 0.5;
    101. mat4 scaleMat = mat4(
    102. vec4(  S, 0.0, 0.0 ,0.0),
    103. vec4(0.0,   S, 0.0, 0.0),
    104. vec4(0.0, 0.0,   S ,0.0),
    105. vec4(0.0, 0.0, 0.0, 1.0)
    106. );
    107.  
    108. // 2. Rotate around X-axis
    109. float angleX = radians(300.0);
    110. float cX = cos(angleX);
    111. float sX = sin(angleX);
    112. mat4 rotX = mat4(
    113. vec4(1.0, 0.0, 0.0, 0.0),
    114. vec4(0.0,  cX, sX, 0.0),
    115. vec4(0.0, -sX, cX, 0.0),
    116. vec4(0.0, 0.0, 0.0, 1.0)
    117. );
    118.  
    119. // 3. Rotate around Z-axis
    120. float angleZ = radians(20.0);
    121. float cZ = cos(angleZ);
    122. float sZ = sin(angleZ);
    123. mat4 rotZ = mat4(
    124. vec4( cZ, -sZ, 0.0, 0.0),
    125. vec4( sZ,  cZ, 0.0, 0.0),
    126. vec4(0.0, 0.0, 1.0, 0.0),
    127. vec4(0.0, 0.0, 0.0, 1.0)
    128. );
    129.  
    130. // 4. Rotate around Y-axis
    131. float angleY = radians(10.0);
    132. float cY = cos(angleY);
    133. float sY = sin(angleY);
    134. mat4 rotY = mat4(
    135. vec4( cY, 0.0,  sY, 0.0),
    136. vec4(0.0, 1.0, 0.0, 0.0),
    137. vec4(-sY, 0.0,  cY, 0.0),
    138. vec4(0.0, 0.0, 0.0, 1.0)
    139. );
    140.  
    141. // Ortho Sequence
    142. //mat4 projView = mtxOrtho;
    143. //mat4 projView = mtxOrtho * scaleMat;
    144. //mat4 projView = mtxOrtho * scaleMat * rotX;
    145. //mat4 projView = mtxOrtho * scaleMat * rotX * rotZ;
    146. //mat4 projView = mtxOrtho * scaleMat * rotX * rotZ * rotY;
    147.  
    148. //Perspective Sequence
    149. //mat4 projView = mtxPersp;
    150. //mat4 projView = mtxPersp * transMat;
    151. //mat4 projView = mtxPersp * transMat * rotX;
    152. //mat4 projView = mtxPersp * transMat * rotX * rotZ;
    153. mat4 projView = mtxPersp * transMat * rotX * rotZ * rotY;
    154.  
    155. // OUTPUT
    156.  
    157. layout(location = 0) out vec3 fragColor;
    158.  
    159. void main() {
    160. int face = gl_VertexIndex / 6;
    161. vec3 pos = cubeVertices[gl_VertexIndex];
    162. fragColor = faceColors[face];
    163.  
    164. gl_Position = projView * vec4(pos, 1.0);
    165. }
    166.  

    Код (C):
    1. #version 450
    2.  
    3. layout(location = 0) in vec3 fragColor;
    4. layout(location = 0) out vec4 outColor;
    5.  
    6. void main() {
    7.     outColor = vec4(fragColor, 1.0);
    8. }

    Напоминаю, что компилятор языка GLSL поставляется с пакетом Vulkan, он встраивается в переменные среды, поэтому его можно вызывать прямо с командной строки.
    Код (DOS):
    1. @echo off
    2. echo Compiling vertex shader...
    3. glslc -fshader-stage=vertex vertex.vert -o vertex.spv
    4. if %errorlevel% equ 0 (
    5.     echo Success: vertex.spv generated.
    6. ) else (
    7.     echo Error: compilation failed.
    8. )
    9. pause

    HelloCube0.jpg
     

    Вложения:

    • vkHelloCube.zip
      Размер файла:
      51,5 КБ
      Просмотров:
      33
    Последнее редактирование: 29 июн 2026
    Application и Mikl___ нравится это.
  2. ml64

    ml64 Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    60

    Система координат Вулкан


    Ориентация осей


    В Северном полушарии Оси координат Вулкана ориентированы следующим образом:
    +Z - это направление, в котором фотоны летят из монитора на Вашу сетчатку.
    +Y смотрит вниз (в отличие от декартовой системы).
    +X смотрит вправо (как в декартовой системе).
    Таким образом, чтобы привести Вулкан к декартовой системе, надо применить следующую матрицу:
    mat4 mtxScale = mat4(
    vec4( S, 0.0, 0.0 ,0.0),
    vec4(0.0, -S, 0.0, 0.0), //Right-hand
    vec4(0.0, 0.0, S ,0.0),
    vec4(0.0, 0.0, 0.0, 1.0)
    Если этого не сделать, то всё будет в зеркальном отображении относительно плоскости XZ.

    Позиционирование объекта


    Если (как, например, в случае с нашим кубом) точка 0,0,0 находится в центре сцены, то мы не увидим всей сцены. Нужно отодвинуть всю сцену на достаточное расстояние от себя, т.е. в направлении -Z. В примере выше я сделал это так:
    Код (C):
    1. // Step 1. Translate
    2. float dx = 0.0;
    3. float dy = 0.0;
    4. float dz = -2.0;
    5. mat4 mtxTrans = mat4(
    6. vec4(1.0, 0.0, 0.0, 0.0),
    7. vec4(0.0, 1.0, 0.0, 0.0),
    8. vec4(0.0, 0.0, 1.0, 0.0),
    9. vec4( dx,  dy,  dz, 1.0)
    10. );
    Обращаю внимание, что матрица row-major (по горизонтали). Не помню, как это называется в русской линейной алгебре. Потом переведу, чтобы сейчас не сбиваться с мысли.

    Направление взгляда


    Чтобы создать эффект прогулки от первого лица, надо повернуть всю сцену вокруг оси X. На какой угол? - Сейчас определим.
    Как показано выше, Вулкан смотрит на сцену сверху вниз.
    Фотоны летят на Вас в направлении +Z, а Вы смотрите на объект в направлении -Z.
    В реальной жизни (я имею в виду, конечно же, BIM-моделирование) мы считаем, что +Z - это направление от земли к небу, т.е. наш взгляд условно параллелен плоскости XY.
    Следовательно, чтобы Вулкан рисовал сцену так, как мы видим реальный мир, нам нужно повернуть всю сцену вокруг оси X на угол 90 +/- 30 градусов.
    Я повернул на 60, чтобы взгляд был чуть сверху.
    Код (C):
    1. // Step 3. Rotate around X-axis
    2. float angleX = radians(60.0);
    3. float cX = cos(angleX);
    4. float sX = sin(angleX);
    5. mat4 rotX = mat4(
    6. vec4(1.0, 0.0, 0.0, 0.0),
    7. vec4(0.0,  cX, -sX, 0.0),
    8. vec4(0.0,  sX,  cX, 0.0),
    9. vec4(0.0, 0.0, 0.0, 1.0)
    10. );
    Классическая матрица поворота, тут ничего волшебного.

    Примечание


    Какие-то цифры, коэффициенты могут отличаться от примера. Такое может быть, т.к. я выкладываю в процессе разработки, потому что потом уже будет лень что-то форматировать. Даже не то, что лень, а вайб пройдёт и пойдут уже другие идеи. Поэтому фиксирую, как есть.
    --- Сообщение объединено, 29 июн 2026 ---

    Надо уточнить!


    А вот и нет.
    Сам Khronos пишет, что: "Vulkan requires the right hand NDC space compared to GL that requires the left hand. In other words the (-1, -1) NDC coordinate maps to the top left corner for Vulkan and to the bottom left corner for GL".
    И добавляет: "In practice, if a Vulkan application ignored this convention the final output will end up flipped in the Y axis and inside out."
    Короче: у меня куб задан в декартовой системе координат:

    Код (C):
    1. const vec3 cubeVerts[8] = {
    2. vec3(-0.5, -0.5, -0.5), // 0
    3. vec3(+0.5, -0.5, -0.5), // 1
    4. vec3(+0.5, +0.5, -0.5), // 2
    5. vec3(-0.5, +0.5, -0.5), // 3
    6. vec3(-0.5, -0.5, +0.5), // 4
    7. vec3(+0.5, -0.5, +0.5), // 5
    8. vec3(+0.5, +0.5, +0.5), // 6
    9. vec3(-0.5, +0.5, +0.5)  // 7
    10. };
    11.  
    12. // Cube faces (36 vertices, 6 faces, 2 triangles per face)
    13. const vec3 cubeVertices[36] = {
    14. // Face -Z (Bottom) – White
    15. cubeVerts[0], cubeVerts[3], cubeVerts[2],
    16. cubeVerts[0], cubeVerts[2], cubeVerts[1],
    17. // Face -Y (Front) – Blue
    18. cubeVerts[0], cubeVerts[1], cubeVerts[5],
    19. cubeVerts[0], cubeVerts[5], cubeVerts[4],
    20. // Face +X (Right) – Red
    21. cubeVerts[1], cubeVerts[2], cubeVerts[6],
    22. cubeVerts[1], cubeVerts[6], cubeVerts[5],
    23. // Face +Y (Back) – Green
    24. cubeVerts[2], cubeVerts[3], cubeVerts[7],
    25. cubeVerts[2], cubeVerts[7], cubeVerts[6],
    26. // Face -X (Left) – Orange
    27. cubeVerts[0], cubeVerts[4], cubeVerts[7],
    28. cubeVerts[0], cubeVerts[7], cubeVerts[3],
    29. // Face +Z (Top) – Yellow
    30. cubeVerts[4], cubeVerts[5], cubeVerts[6],
    31. cubeVerts[4], cubeVerts[6], cubeVerts[7]
    32. };
    Чтобы не запутаться, я держу на столе кубик Рубика.
    И могу сказать: Вулкан рисовал куб в зеркальном отражении относительно плоскости XZ,
    пока я не умножил координату Y на -1.
    Код (C):
    1. float S = 1.0;
    2. mat4 mtxScale = mat4(
    3. vec4(  S, 0.0, 0.0 ,0.0),
    4. vec4(0.0,  -S, 0.0, 0.0), //Right-hand
    5. vec4(0.0, 0.0,   S ,0.0),
    6. vec4(0.0, 0.0, 0.0, 1.0)
    7. );
    --- Сообщение объединено, 29 июн 2026 ---

    К вопросу о направлении оси Z


    Подтверждение этому - преобразование:
    Код (C):
    1. // Step 1. Translate
    2. float dx = 0.0;
    3. float dy = 0.0;
    4. float dz = -2.0;
    5. mat4 mtxTrans = mat4(
    6. vec4(1.0, 0.0, 0.0, 0.0),
    7. vec4(0.0, 1.0, 0.0, 0.0),
    8. vec4(0.0, 0.0, 1.0, 0.0),
    9. vec4( dx,  dy,  dz, 1.0)
    10. );
    dx = +0.5 двигает вправо, dy = +0.5 двигает вниз, dz = -3.0 двигает назад
    Всё-таки я прав - с оговоркой: если моя матрица перспективы правильная:
    Код (C):
    1. // Option 2. Perspective Projection
    2. float aspect = 1.0; // 512/512
    3. float fovY = radians(60.0);
    4. float nearZ = 0.1; // Near plane at z_eye = -0.1
    5. float farZ = 10.0; // Far plane at z_eye = -10.0
    6.  
    7. float p11 = 1.0 / tan(fovY * 0.5);
    8. float p00 = p11 / aspect;
    9. float p22 = -farZ / (farZ - nearZ);
    10. float p32 = -1.0; // Makes w_clip = -z_eye
    11. float p23 = nearZ * p22;
    12.  
    13. mat4 mtxPersp = mat4(
    14. vec4(p00, 0.0, 0.0, 0.0),
    15. vec4(0.0, p11, 0.0, 0.0),
    16. vec4(0.0, 0.0, p22, p32),
    17. vec4(0.0, 0.0, p23, 0.0)
    18. );
    --- Сообщение объединено, 29 июн 2026 ---
    Да, моя перспектива правильная и понимание координат Вулкан - тоже.
    Это подтверждается результатами преобразований ортогональной проекции:

    Код (C):
    1. // Step 1. Translate
    2. float dx = [COLOR=#00b300][B]0.5[/B][/COLOR];
    3. float dy = [COLOR=#00b300][B]0.5[/B][/COLOR];
    4. float dz = [COLOR=#ff0000][B]-0.5[/B][/COLOR];
    5. mat4 mtxTrans = mat4(
    6. vec4(1.0, 0.0, 0.0, 0.0),
    7. vec4(0.0, 1.0, 0.0, 0.0),
    8. vec4(0.0, 0.0, 1.0, 0.0),
    9. vec4( dx,  dy,  dz, 1.0)
    10. );
    Affine.jpg
     

    Вложения:

    Последнее редактирование: 29 июн 2026
    Mikl___ нравится это.