Проблема при импорте библиотек в Visual Studio Code
Хочу использовать библиотеку pyfiglet
С помощью pip install установил её
В консоли проверил работоспособность библиотеки, все работает, а значит импортировалось нормально вроде
Но вот в Visual Studio Code при использовании строки
from pyfiglet import Figlet
возникает ошибка Import «pyfiglet» could not be resolved Pylance (reportMissingImports)
Помню раньше была такая же проблема с requests, но проблему решил, а как решил не помню и найти не могу
Помогите пожалуйста
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Проблема при установке Visual Studio: error code 2324
В общем у меня отказал дизайн формы, после удаления программы при установке пишет error code 2324.
Проблема с Visual Studio Code
привет, больше не работает Format Document With / HTML Language Features.выделяется целая.
Проблема Debug в Visual Studio Code
Здрасьте. Пытаюсь запустить код в Visual Studio Code через Run => Start Debugging => Chrome.
Проблема с wsl в Visual studio code
Всем привет!Относительно недавно начал кодить на Vscode B Windows ,и вот сегодня при втором запуске.
Почему у меня MASM32 не правильно работает в Visual studio когда уже установлен внутри настройки visual studio code ?
Почему у меня MASM32 не правильно работает в Visual studio когда уже установлен внутри настройки.
Регистрация: 26.10.2021
Сообщений: 5
Уже не нужна помощь все таки нашёл как исправить
Файл — Настройки — Параметры — Расширения — Pylance и добавил Extra Paths до папки с библиотеками
Извините, за беспокойство
Регистрация: 26.10.2021
Сообщений: 5
По всей видимости проблема не решилась, так как теперь вместо Import «pyfiglet» could not be resolved Pylance (reportMissingImports) пишет что нет модуля с таким именем при запуске кода, хотя пока писал сам код VS Code не жаловался(
Снова помогите
Am I evil? Yes, I am!
![]()
![]()
16119 / 9755 / 2730
Регистрация: 21.10.2017
Сообщений: 21,622
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Зачем для создания формы на Angular использовать Visual Studio и Visual Studio Code?
Мне нужно написать форму на ангуляре, которая будет выполнять Select, Insert,Delete из базы данных.
при компиляции проэкт невидит библиотек фреймворка(Visual studio 2010)
Подключил библиотеки к проэкту путём — (нажмите правой кнопкой на «Ссылки в дереве объектов».
Ошибка при отладке Unity и Visual Studio Code
Сначала запускаю отладку в Visual Studio Code, потом нажимаю воспроизведение в самой Unity в окне.
При выделении добавить тег (visual studio code)
Доброго времени суток, подскажите пожалуйста, как при выделении текста в visual studio code.
Неполадки при вставке текста в Visual Studio Code
Добрый день! Не знаю, в какой раздел писать, но проблема касается sass, а значит, css подойдёт. .

Чем отличается Visual Studio Community и Visual Studio Code?
в чем разница Visual Studio Code или Visual Studio Community. Описание на англиском где я полный.
OpenGL 1: начало работы в VS Code
Цель данного курса заметок по OpenGL является рассмотрение возможностей данной библиотеки и разработка приложения для рисования трехмерной графики.
В проекте будет использоваться компилятор MinGW (GCC 6.3.0).
В качестве IDE для разработки будет использоваться VS Code ввиду её скорости работы и простоты использования.
По аналогии с циклом заметок по Vulkan API для создания окна будет использоваться библиотека glfw3, которая обладает простым интерфейсом, а для инициализации функций OpenGL — glad. Скачанные библиотеки необходимо разместить в директории «dependencies» рядом с директорией проекта, так как одни и те же библиотеки будут использоваться в разных проектах.
Для библиотека glad компонуется на сайте разработчика под необходимые требования, для цикла заметок понадобится выбрать GL: Verison 4.6.
Библиотеки доступны в репозитории: dependencies.
Настройка правил сборки
По большей части данный раздел повторяет оригинальную заметку Vulkan API 01.
Для начала создадим директории для хранения исходных текстов программ (*.c, *.cpp) и назовем её «src«. Внутри этой директории создадим файл «main.cpp«.
А так же создадим папку для хранения заголовочных файлов (*.h, *.hpp) и назовем её «include«.
После этого настроим задачу сборки по умолчанию из меню «Терминал» выбрав одноименный пункт из этого меню. Содержимое меню представлено на рисунке 1.
Среда разработки уточнит адрес исполняемого файла компилятора и создаст файл.

В конфигурации по умолчанию не используются никакие библиотеки и собирается текущий открытый в редакторе файл как исполняемый.
Важное примечание: так как для ОС Windows нет особой разницы для написания пути через прямой или обратный слеш, то будет использоваться прямой для совместимости с ОС Linux.
Как следствие автор заменил все двойные обратные слеши на одинарные прямые. Отредактированная версия оригинального скрипта:
< "tasks": [ < "type": "cppbuild", "label": "C/C++: g++.exe сборка активного файла", "command": "C:/MinGW/bin/g++.exe", "args": [ "-fdiagnostics-color=always", "-g", "$", "-o", "$/$.exe" ], "options": < "cwd": "$" >, "problemMatcher": [ "$gcc" ], "group": < "kind": "build", "isDefault": true >, "detail": "Задача создана отладчиком." > ], "version": "2.0.0" >
Стоит заметить, что ввиду форматирования страницы некоторые строки из файла занимают 2 и более в браузере.
Ключ «-g» с 9 строки нам не нужен. Его можно удалить.
В рамках курса заметок будет использоваться подход с дроблением исходных текстов программы на разные файлы с последующей компиляцией их в общий исполняемый файл. Для того чтобы собрать все файлы из папки src по шаблону «*.cpp» из директории src заменим 9 строку (10, если не удалять ключ -g) с адресом на:
"$/src/*.cpp", "$/../dependencies/glad/src/glad.c",
Примечание: дополнительно указываются исходные тексты библиотеки glad для компиляции с проектом.
В дальнейшем при добавлении новых директорий с исходниками файл будет дополняться.
Добавим директорию с заголовочными файлами:
"-I$/include",
При желании можно указать конкретную версию компилятора:
"--std=c++11",
Добавим папки include и lib от GLFW, а так же include от GLAD. Так как они находятся на уровень выше директории проекта необходимо добавить «../«:
"-I$/../dependencies/GLFW/include", "-L$/../dependencies/GLFW/lib-mingw", "-I$/../dependencies/glad/include",
И добавим флаги:
"-static", "-lopengl32", "-lglfw3dll",
Разберемся с флагами:
- static — предотвращает линковку с разделяемыми библиотеками в системах, которые поддерживают динамическую линковку;
- lopengl32 — использует библиотеку OpenGL;
- lglfw3dll — использует статическую библиотеку GLFW3, подразумевающую дальнейшую работу приложения с динамической библиотекой.
В конце необходимо изменить имя исполняемого файла, для этого заменим строку:
Благодаря этой замене исполняемый файл будет создан в корне проекта с именем директории.
В результате файл должен иметь следующее содержание:
< "tasks": [ < "type": "cppbuild", "label": "C/C++: g++.exe сборка активного файла", "command": "C:/MinGW/bin/g++.exe", "args": [ "-fdiagnostics-color=always", "$/src/*.cpp", "$/../dependencies/glad/src/glad.c", "-I$/include", "--std=c++11", "-I$/../dependencies/GLFW/include", "-L$/../dependencies/GLFW/lib-mingw", "-I$/../dependencies/glad/include", "-static", "-lopengl32", "-lglfw3dll", "-o", "$/$.exe" ], "options": < "cwd": "$" >, "problemMatcher": [ "$gcc" ], "group": < "kind": "build", "isDefault": true >, "detail": "Задача создана отладчиком." > ], "version": "2.0.0" >
После настроек сборки необходимо указать редактору директории с заголовочными файлами.
Настройка плагина intelliSense
В директории «.vscode» необходимо создать файл «c_cpp_properties.json» со следующим содержимым:
< "configurations": [ < "name": "some_name", "includePath": [ "$/include", "$/../dependencies/GLFW/include", "$/../dependencies/glad/include" ], "compilerPath": "C:/MinGW/bin/g++.exe", "cStandard": "c11", "cppStandard": "c++11", "intelliSenseMode": "gcc-x86" > ], "version": 4 >
В данном файле можно изменить настройки intelliSense:
- includePath — указать директории в которых дополнительно необходимо искать заголовочные файлы;
- compilerPath — путь до компилятора;
- cStandard — стандарт языка С;
- cppStandart — стандарт языка С++;
- intelliSenseMode — режим работы intelliSense.
Важно помнить что эти настройки распространяются только на плагин intelliSense, а не на компилятор
Создание окна
Рассмотрим следующий код:
#include #include #include #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define WINDOW_CAPTION "OPENGL notes on rekovalev.site" // Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна void framebuffer_size_callback(GLFWwindow* window, int width, int height) < glViewport(0, 0, width, height); >int main(void) < GLFWwindow* window; // Указатель на окно GLFW3 // Инициализация GLFW3 if (!glfwInit()) < std::cout // Завершение работы с GLFW3 перед выходом atexit(glfwTerminate); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Мажорная версия спецификаций OpenGL glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); // Минорная версия спецификаций OpenGL glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Контекст OpenGL, который поддерживает только основные функции // Создание окна GLFW3 с заданными шириной, высотой и заголовком окна window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION, NULL, NULL); if (!window) < std::cout // Установка основного контекста окна glfwMakeContextCurrent(window); // Установка callback-функции для изменения размеров окна и буфера кадра glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // Загрузка функций OpenGL с помощью GLAD if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) < std::cout // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Пока не произойдет событие запроса закрытия окна while(!glfwWindowShouldClose(window)) < // Очистка буфера цвета glClear(GL_COLOR_BUFFER_BIT); // Тут производится рендер // . // Представление содержимого буфера цепочки показа на окно glfwSwapBuffers(window); // Обработка системных событий glfwPollEvents(); >>
В определении функции main инициализируется glfw вызовом функции glfwInit(). Сразу после инициализации с помощью функции atexit задается вызов функции glfwTerminate, которая будет вызвана перед закрытием приложения. Такой подход позволяет избежать дублирования фрагментов кода с вызовом в случае ошибок инициализации библиотек, а так же возникновения «segmentation fault» ошибок деструкторов глобальных переменных в следствии явного вызова функции glfwTerminate в конце функции main.
С помощью функции glfwWindowHint задаются параметры для создаваемого окна, такие как: мажорная и минорная версии OpenGL и содержание контекста (поддержка расширений).
Для создания окна используется функция glfwCreateWindow, которая принимает в качестве аргументов ширину и высоту окна в пикселях, текст заголовка окна, а так же контекст монитора и контекст окна для обмена ресурсами. Последние два параметра не используются и заместо них передается NULL. В случае ошибки при создании окна выдается сообщение об ошибке и завершается работа приложения.
Далее производится установка основного контекста окна с помощью glfwMakeContextCurrent, а так же устанавливается callback-функция на событие изменения размеров окна, которая изменяет размеры буфера кадра с помощью функции glfwSetFramebufferSizeCallback. Рассмотрим передаваемую функцию подробнее:
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
Данная функция принимает в качестве аргументов указатель на объект структуры окна GLFWwindow, а так же новые ширину и высоту. В определении данной функции производится вызов функции glViewport, которая изменяет размеры буфера кадра.
Следующим этапом инициализации служит вызов функции gladLoadGLLoader из библиотеки GLAD, которая инициализирует функции OpenGL, так как в зависимости от драйверов функции могут быть недоступны и располагаться по разным адресам в памяти. В случае ошибки выдается соответствующее сообщение и завершается работа приложения.
Теперь можно задать цвет для функции очистки буфера с помощью glClearColor (r,g,b,a).
Важное замечание: функция glClearColor принимает значения цветов в диапазоне 0.0f-1.0f, что эквивалентно диапазону 0-255, который можно преобразовать с помощью формулы: компонента_цвета / 255.0f.
Далее следует жизненный цикл окна, пока окну не придёт сигнал закрытия от системы. Внутри этого цикла производится очистка буфера цвета, представление буфера на поверхность окна и обработка событий от ОС вызовом функции glfwPollEvents.
Теперь проект можно собрать, вызвав в меню «Терминал» пункт «Запустить задачу сборки».
Перед запуском необходимо положить файл glfw3.dll в корень проекта.
Дополнение
В репозиторий добавлена вертикальная синхронизация.
После инициализации контекста окна:
// Установка основного контекста окна glfwMakeContextCurrent(window); // Установка callback-функции для изменения размеров окна и буфера кадра glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSwapInterval(1); // Вертикальная синхронизация // Загрузка функций OpenGL с помощью GLAD if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
Подробнее об этом можно прочитать в соответствующей заметке: ограничение частоты кадров.
Сборка под архитектуру x64
Для сборки 64-х разрядного приложения под OS Windows потребуется отдельная версия MinGW, которую можно скачать с репозитория (есть онлайн установщик, ссылка на который доступна в описании репозитория).
Изменим файл .vscode/tasks.json, добавив туда конфигурацию для сборки х64:
< "tasks": [ < "type": "cppbuild", "label": "C/C++: g++.exe сборка активного файла", . "detail": "Задача создана отладчиком." >, < "type": "cppbuild", "label": "C/C++ x64: g++.exe сборка активного файла", "command": "C:/MinGW64/bin/g++.exe", "args": [ "-fdiagnostics-color=always", "$/src/*.cpp", "$/../dependencies/glad/src/glad.c", "-I$/include", "--std=c++11", "-I$/../dependencies/GLFW/include", "-L$/../dependencies/GLFW/lib-mingw-w64lib-mingw-w64", "-I$/../dependencies/glad/include", "-static", "-lopengl32", "-lglfw3dll", "-o", "$/$.exe" ], "options": < "cwd": "$" >, "problemMatcher": [ "$gcc" ], "group": < "kind": "build", "isDefault": true >, "detail": "Задача создана отладчиком." > ], "version": "2.0.0" >
Важное замечание: архитектура файла glfw3.dll должна соответствовать архитектуре собранного приложения, иначе приложение завершит работу без вывода соответствующей ошибки.
Использование Makefile в VScode
В процессе добавления кросплатформенных правил сборка приложения через .vscode/tasks.json становится неподъемной — требуется дублировать большой объем аргументов в аргументах задачи сборки, а так же отстутствует возможность скрыть задачи не подходящие под имеющуюся архитектуру.
Для решения данной проблемы можно воспользоваться классическим способом сборки C/C++ приложений — использование Makefile. Рассмотрим задачу использования Makefile в VS code для задач сборки OpenGL приложения.
Makefile — файл, содержащий в себе набор инструкций для утилиты make. Инструкции группируются в «цели». Цели могут выстраиваться в дерево зависимых «целей». Цель по умолчанию — all, зачастую так же присутствует цель clean, выполняющая очистку проекта.
Важное замечание: для сборки Makefile под ОС Windows необходимо установить утилиту GNU-make с официального сайта и добавить её адрес в переменную среды Path. В семействе Unix-систем данная утилита является частью системы.
Изменим файл .vscode/tasks.json, оставив одну задачу:
< "tasks": [ < "type": "cppbuild", "label": "C/C++: make сборка", "command": "make", "args": [], "options": < "cwd": "$workspaceRoot>" >, "problemMatcher": [ "$gcc" ], "group": < "kind": "build", "isDefault": true >, "detail": "Задача создана отладчиком." > ], "version": "2.0.0" >
Так как по умолчанию будет выполнятся цель all необходимо сделать несколько задач, либо добавить ввод с клавиатуры интересующей задачи:
< "tasks": [ < "type": "cppbuild", "label": "C/C++: make сборка", "command": "make", "args": [ "$" ], "options": < "cwd": "$" >, "problemMatcher": [ "$gcc" ], "group": < "kind": "build", "isDefault": true >, "detail": "Задача создана отладчиком." > ], "inputs": [ < "id": "target", "description": "Цель сборки (all, list, clean)", "default": "all", "type": "promptString" >, ], "version": "2.0.0" >
Теперь при запуске задачи сборки в VS code будет отображено поле для ввода цели сборки make с подсказкой основных целей и all по умолчанию. Пример такого окна ввода изображен на рисунке 2.

Теперь можно создать основной файл Makefile в корневой директории проекта.
Комментарии начинаются с символа #
Makefile поддерживает ветвление условным оператором ifeq, который может сравнивнить переменную среды и строку. В данном проекте данный оператор будет использоваться для определения целей и значений переменных, которые зависят от целевой платформы (переменная OS). Пример:
ifeq ($(OS), Windows_NT) # Если ОС - Windows else # Остальные ОС endif
Так же для сборки x32 приложений будет создана цель, на основании которой так же будет выполняться ветвление (переменная MAKECMDGOALS), но только в рамках ОС Windows. Сборка x64 будет выполняться по умолчанию.
Переменные по правилам написания Makefile используя оператор = могут изменять значение, с помощью оператора := могут быть константными при задании значения, или же дополняться используя +=
В созданном файле определим значения переменных CFLAGS (опции компилятора) и LDFLAGS (опции линкера) на основании старого tasks.json:
# Опции компилятора CFLAGS += -c CFLAGS += -I./include CFLAGS += -I../dependencies/GLFW/include CFLAGS += -I../dependencies/glad/include # Опции линкера LDFLAGS += --std=c++11
Далее следует определить платформозависимые опции линкера:
# Архитектурозависимые опции линкера ifeq ($(OS), Windows_NT) # GLFW в зависимости от архитектуры ifeq ($(MAKECMDGOALS), x32) LDFLAGS += -L../dependencies/GLFW/lib-mingw else LDFLAGS += -L../dependencies/GLFW/lib-mingw-w64 endif LDFLAGS += -static LDFLAGS += -lglfw3dll LDFLAGS += -lopengl32 else LDFLAGS += -lglfw LDFLAGS += -lGL endif
Важное замечание: для ОС Linux необходимо установить пакет с библиотекой GLFW3. В зависимости от дистрибутива имя пакета может меняться:
- libglfw3-dev — Ubuntu/Debian;
- glfw-x11 или glfw-wayland — Arch linux;
- glfw-devel — Fedora.
Важное замечание: для ОС Windows требуется флаг -static, для Linux данный флаг не требуется.
Определим переменные, связанные с библиотекой GLAD:
# Библиотека GLAD GLAD := ../dependencies/glad/src/glad.c GLAD_O := $(GLAD:.c=.o)
Примечание: конструкция $(GLAD:.c=.o) выполняет замену расширения файлов в переменной GLAD с .c на .o.
С помощью утилиты wildcard получим все файлы из директории src:
# Файлы из директории src SOURCES_C = $(wildcard src/*.c) SOURCES_CPP = $(wildcard src/*.cpp)
Определим название директории с объектными файлами и имена таких файлов:
# Директория с объектными файлами OBJ_DIR := Obj # Объектные файлы OBJECTS = $(addprefix $(OBJ_DIR)/,$(SOURCES_CPP:src/%.cpp=%.o))
Осталось определить последние платформозависимые переменные:
# Компилятор и директория проекта ifeq ($(OS), Windows_NT) # С возможностью сборки x32 ifeq ($(MAKECMDGOALS), x32) CC = C:/MinGW/bin/g++.exe else CC = C:/MinGW64/bin/g++.exe endif PROJECT_DIR = $(shell echo %cd%) PATH_SEPARATOR = \\ # Имя исполняемого файла EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))).exe else CC = g++ PROJECT_DIR = $(shell pwd) PATH_SEPARATOR = / # Имя исполняемого файла EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))) endif
Теперь можно приступить к определению целей. Пример общего вида цели:
цель1: зависимость1 зависимость2 зависимость3 команда_отображаемая_в_консоли @команда_неотображаемая_в_консоли
Примечание: цель может не иметь зависимостей от других целей.
Основная цель all зависит от исполняемого файла, который тоже является целью:
# Цель по умолчанию, зависит от EXECUTABLE all: $(EXECUTABLE)
Цель EXECUTABLE в свою очередь зависит от объектных файлов, объектного файла GLAD_O и наличия директории для объектных файлов, а в качестве действия выполняет сборку исполняемого файла с использованием флагов LDFLAGS.
Здесь в свою очередь $@ — переменная с именем текущей цели (EXECUTABLE).
Важное замечание: флаги линковки должны быть заданы после объектных файлов во избежание ошибки сборки.
Цель для сборки GLAD_O имеет следующий вид:
# Цель для сборки GLAD $(GLAD_O): $(GLAD) $(CC) $(CFLAGS) $< -o $@
Цель OBJ_DIR необходима для решения возможных ошибок во время сборки объектных файлов, связанных с отсутствием таковой директории в корне проекта:
# Цель для создания директории с объектными файлами $(OBJ_DIR): @mkdir $(OBJ_DIR)
Цель сборки объектных файлов имеет следующий вид:
# Цель сборки объектных файлов $(OBJ_DIR)/%.o: src/%.cpp $(CC) $(CFLAGS) $< -o $@
Здесь $ переменная с зависимостями данной цели.
В качестве вспомогательной добавим цель list, которая выводит все объектные файлы, учавствующие в сборке:
# Цель вывода всех файлов, учавствтующих в сборке list: @echo "В сборке участвуют:" $(OBJECTS)
Осталось добавить цель clean, которая является платформозависимой из-за особенностей работы команды rm под Windows:
# Очистка ifeq ($(OS), Windows_NT) clean: $(OBJ_DIR) @rmdir /s /q $(OBJ_DIR) else clean: $(OBJ_DIR) @rm -f $(EXECUTABLE) $(OBJECTS) endif
Итоговый вид Makefile:
# Компилятор и директория проекта ifeq ($(OS), Windows_NT) # С возможностью сборки x32 ifeq ($(MAKECMDGOALS), x32) CC = C:/MinGW/bin/g++.exe else CC = C:/MinGW64/bin/g++.exe endif PROJECT_DIR = $(shell echo %cd%) PATH_SEPARATOR = \\ # Имя исполняемого файла EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))).exe else CC = g++ PROJECT_DIR = $(shell pwd) PATH_SEPARATOR = / # Имя исполняемого файла EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))) endif # Опции компилятора CFLAGS += -c -Wall CFLAGS += -I./include CFLAGS += -I../dependencies/GLFW/include CFLAGS += -I../dependencies/glad/include # Опции линкера LDFLAGS += --std=c++11 # Архитектурозависимые опции линкера ifeq ($(OS), Windows_NT) # GLFW в зависимости от архитектуры ifeq ($(MAKECMDGOALS), x32) LDFLAGS += -L../dependencies/GLFW/lib-mingw else LDFLAGS += -L../dependencies/GLFW/lib-mingw-w64 endif LDFLAGS += -static LDFLAGS += -lglfw3dll LDFLAGS += -lopengl32 else LDFLAGS += -lglfw LDFLAGS += -lGL endif # Библиотека GLAD GLAD := ../dependencies/glad/src/glad.c GLAD_O := $(GLAD:.c=.o) # Файлы из директории src SOURCES_C = $(wildcard src/*.c) SOURCES_CPP = $(wildcard src/*.cpp) # Директория с объектными файлами OBJ_DIR := Obj # Объектные файлы OBJECTS = $(addprefix $(OBJ_DIR)/,$(SOURCES_C:src/%.c=%.o) $(SOURCES_CPP:src/%.cpp=%.o)) # Для x32 сборки под Windows ifeq ($(OS), Windows_NT) ifeq ($(MAKECMDGOALS), x32) x32: all endif endif # Цель по умолчанию, зависит от EXECUTABLE all: $(EXECUTABLE) # Цель сборки исполняемого файла, зависит от OBJ_DIR, OBJECTS и GLAD_O $(EXECUTABLE): $(OBJ_DIR) $(OBJECTS) $(GLAD_O) $(CC) $(OBJECTS) $(GLAD_O) $(LDFLAGS) -o $@ # Цель для сборки GLAD $(GLAD_O): $(GLAD) $(CC) $(CFLAGS) $< -o $@ # Цель для создания директории с объектными файлами $(OBJ_DIR): @mkdir $(OBJ_DIR) # Цель сборки объектных файлов $(OBJ_DIR)/%.o: src/%.c $(CC) $(CFLAGS) $< -o $@ $(OBJ_DIR)/%.o: src/%.cpp $(CC) $(CFLAGS) $< -o $@ # Цель вывода всех файлов, учавствтующих в сборке list: @echo "В сборке участвуют:" $(OBJECTS) # Очистка ifeq ($(OS), Windows_NT) clean: $(OBJ_DIR) @rmdir /s /q $(OBJ_DIR) else clean: $(OBJ_DIR) @rm -f $(EXECUTABLE) $(OBJECTS) endif
Использование Makefile позволит ускорить сборку проекта на последних заметках в виду объема компилируемого кода, так как неизмененные объектные файлы хранятся в отдельной папке и будут использованы для последующей компоновки с измененными. При изменении заголовочных файлов необходимо пересобрать весь проект с использованием цели clean:
make clean && make
Важное замечание: последующие заметки будут постепенно переведены на работу с Makefile, что может привести к отделению HEAD в git-директории. Для решения данной проблемы необходимо выполнить команду:
git checkout master
Заключение
В рамках данной заметки была произведена установка библиотек GLFW, GLAD и OpenGL, настройка VS code для работы с ними и сборка программы, создающей окно для дальнейшей работы.
Проект доступен в публичном репозитории: 01
Библиотеки: dependencies
Нужна помощь по настройке VS Code для работы с библиотеками от CS50

Начинал учёбу с их облачной IDE, не обращая внимание на дисклеймер.

А потом кааак дошло! Пулей скачал архив своих учебных говнокодов, ибо их там уже столько много, что было бы жалко их потерять. Начал готовить плацдарм для перехода на стационарную IDE. Сначала хотел скачать VS Community Edition, но понял, что это не для моего интернета. VS Code хватит до лучших времён.
Итак, что было сделано. Установил VS Code, в соответствии с инструкцией накатил расширения С/C++ от мелкомягких. Поставлен, обновлён и добавлен в PATH терминал msys64. Через него скачена чихуйня для компилирования gcc, g++ и gdb. Затем через PATH подключил её к терминалу VS Code. Хватило толку сделать всё правильно, компиляция работает. Затык случился на гарвардских учебных библиотеках.
На установку cs50.h нашёл мануал. Инструция заключается в том, чтобы скачать с гитхаба cs50.c и cs50.h, положить в директорию с файлом, в котором она подключается, и через "" вместо <> прописать в строке #include нужного файла. Далее скомпилировать этот файл в связке с cs50.c. Это чисто проверка работоспособности библиотеки. После этого этапа должен был быть этап автоматизации подключения библиотеки, но перейти к нему я не смог, ибо первая часть выполнена некорректно. Неясно, в чём эта некорректность заключается. Нет файла в директории, хоть и он физически в ней находится.

Помимо cs50.h, мне ещё предстоит где-то наковырять stdio.h, ctype.h, math.h, stdlib.h, string.h, strings.h, time.h в соответствии с https://manual.cs50.io/
Либо есть вариант забить на CS50 и найти другой курс по Computer Science, в котором все функции будут создаваться вручную, а не выдёргиваться из непонятных библиотек.
Поддержать


1.3K постов 11K подписчиков
Подписаться Добавить пост
Правила сообщества
- Будьте взаимовежливы, аргументируйте критику
- Приветствуются любые посты по тематике программирования
- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества
1 год назад
Запомни,
#include ищет в директории include компилятора и прочим добавочные.
#include "filename" ищет в директории файла.
нет в директории компилятора, поэтому ошибка.
А почему написал одно, а по факту другое - файл сохранять надо.
stdio.h, ctype.h, math.h, stdlib.h, string.h идут с компилятором.

раскрыть ветку
1 год назад
Так getname в папке ubuntu а cs50 в project
раскрыть ветку
1 год назад
в gcc у тебя не указаны пути для библиотек. Это ж линуксовский компилятор, ему нужно четко указывать куда откуда и почем брать.
По идее строка должна выглядеть как-то так:
gcc -o main.exe -Ic:/myIncludeDir/ main.cpp cs50.cpp
Где I - это заглавная i.
PS а так, готовьтесь изучать флаги gcc или переходите на системы компиляции типа cmake.
раскрыть ветку
Похожие посты
23 часа назад

Ответ на пост «Тряпка в банке оливок iberica - прошу совет как действовать | часть 1»
Купили с супругой диски компании "skad" через маркетплейс. После получения, как пришло время переобувки, отвез их на шиномонтаж. При балансировке выяснилось, что три диска из четырёх кривые, при этом никаких видимых повреждений ЛКП и металла не было, коробки от производителя так-же были целые.
Зашел на сайт производителя https://skad.ru/ , где имеется вот такая информация:

Пожизненная гарантия на конструкцию колеса.
Решили мы им написать, чтобы они разобрались в данной ситуации, нашли причину такого брака, для исключения его при последующем производстве. В письмо приложили чек о покупке и видеозаписи, доказывающие целостность и кривизну дисков. Возврата денег не просили, т.к. диски покупали не у них, максимум извинений за доставленные неудобства.

Ни даты производства, ни номера партии они не запросили, это им неинтересно, т.к. "Согласно гарантийным обязательствам, размещенным на официальном сайте скад.рф, предварительная примерка осуществляется до шиномонтажа, в ином случае гарантия снимается.")

Может здесь есть их представитель и он ответит, как так получилось, что произведенные вами диски, на которые вы даете ПОЖИЗНЕННУЮ гарантию, судя по информации на сайте, такого ужасного качества. В ответном письме вы сразу начинаете скидывать с себя всю ответственность, ведь на диски установили шины. Но как это может повлиять на такие ужасные диски? Никак! И, разве, кто-то проверяет диски на балансировочном станке при покупке, перед монтажом резины.
Ни качества, ни гарантии, ни желания изучить ситуацию и исправить её у данной компании нет.
Показать полностью 2
1 день назад

Если ты ростом ниже 185, то даже знание плюсов тебе не поможет

4 дня назад

Интересно, а сколько разработчиков в мире используют только свой код?

Показать полностью 1
4 дня назад

Тряпка в банке оливок iberica - прошу совет как действовать | часть 1
Купил около недели назад банку черных оливок без косточки в оранжевом магазине. Приоткрыл банку, слил часть жидкости, чтобы было удобнее доставать. После чего открыл банку полностью и увидел инородный предмет в рассоле. Данный предмет был частично вытянут из банки и сфотографирован мной:

Инородный предмет в оливках iberica - кусок ткани в банке оливок
Который я бережно отжал от маринада и сфотографировал для представителя компании:

Инородный предмет в оливках iberica - кусок ткани, отжатый из банки оливок
Нашел сайт-представительство, есть 2 дистрибьютора данной продукции.
ООО «ЮНЭКТ ЮНИОН»
ООО «МАСТЕР-ТРЕЙД»
Написал в обе компании электронные письма. С вопросом, что это у них за такие нанотехнологии и просьбой разъяснить ситуацию. Хотел сделать скрин письма, но случайно его удалил, ибо del там где prntscr - отстой, но это другая история. В любом случае по почте ответа не получил.
Параллельно почте решил написать в официальную группу вк сообщение сообществу:

Что я ожидал получить:
"Уважаемый . приносим глубочайшие извинения, мы разобрались в ситуации, проблема была на производстве мы обнаружили её благодаря вам, причина в том, что . . . данный предмет не представляет опасности, виновные наказаны, производство проверено . "
Что я получил в ответ:

Ответ я понял для себя так:
1. У них на производстве всё автоматизировано, что исключает попадание инородных предметов в продукцию. Т.е. их вины нет 100%.
2. Угроза 1, что если я решил их обмануть, то должен оплатить их экспертизу. Напрягает что экспертиза будет сделана непонятно кем, непонятно где и на каких условиях.
3. Угроза 2, что если я буду распространять данную информацию, то будет иск в связи с репутационными потерями.
Прошу совет: как поступить, чтобы данную компанию привести в состояние абсолютной лояльности к покупателям их продукции. Физического ущерба нет, фиксировать можно было только мои округленные глаза, поэтому порядок действий не могу определить. Банку с тряпкой храню в пакетике и в морозилке, на всякий случай).
Показать полностью 4
10 дней назад

Что заставляет программистов писать вирусы
Материал был взят и переведен с Рэддита. Приятного прочтения!
1. В 7 классе я ходил на кружок программирования, который фактически превратился в кружок по созданию вредоносных программ. Мы с другом написали программу, которая постоянно открывала на компьютере один сайт для взрослых и врубала звук на полную мощность. У нескольких человек этот сайт открылся прямо на уроке. Было весело.
2. Я написал эту программу ради азарта. Это был аддон для Воркрафта. Он запускался, когда персонаж входил в игру. А потом персонаж получал приглашение в гильдию от игрока с заряженным аккаунтом и сам становился главой гильдии. После этого можно было идти в игровой банк и забрать оттуда все ценное. Написать код было просто, но вот протестировать его работу с помощью приемов социальной инженерии очень сложно. Но мне повезло с первого раза. Прилив адреналина был колоссальным, но я также понимал, что меня, скорее всего, забанят в этой игре. Моей следующей целью была высшая рейдерская гильдия на сервере. Чтобы убедить лидера гильдии участвовать в моем тестировании, понадобился час разговоров по скайпу. Он попался на крючок, и все почти получилось. Я знал, что у этой гильдии игровых ценностей на сотни тысяч долларов. Глава установил аддон, но потом я понял, что он вошел через альтернативного персонажа, не имевшего доступ к богатству гильдии. Так у меня все провалилось. Меня выгнали из гильдии и забанили. Позже мне удалось вернуть свой аккаунт, но без тех ценностей, которые я награбил раньше.
3. В юности я создал несколько троянов удаленного доступа. С их помощью воровал аккаунты в разных играх и продавал их в интернете. Когда я впервые запустил троян, было 200 загрузок и 90 заражений. Половину угнанных аккаунтов я отдал другу, который помогал писать программу. Потом продал два акка и купил попугая, потому что люблю птиц. А потом старший брат объяснил, что все это плохо и незаконно, и я остановился.
4. Раньше вирусы создавались ради демонстрации крутости и были не особо вредными, это во времена Дос и вплоть до Виндовс XP. Потом появились черви для кражи паролей. Потом ботнеты, а они уже только ради денег. Они крадут данные, пароли, откровенные фотки, все подряд, для последующей продажи. Потом киберпреступники научились использовать сторонние компьютеры для майнинга, взлома сайтов и прочего дерьма.
5. У меня есть друг, который мошенничал с кредитками, крал личные данные, информацию с компьютеров, используя для этого кейлоггер, замаскированный под ссылку для скачивания. В школе он начал продавать вещи и одежду всем, включая меня. А через два года за ним приехали из ФБР и увезли, хотя он и был несовершеннолетним. Ему пришлось заключить сделку и вернуть товаров на 50 тысяч долларов. А еще он взломал главу отдела безопасности Xbox, про это есть видео на ютубе.
6. Когда-то я любила троллить людей в чатах, рассказывая, что у меня есть постеры с Бритни Спирс, но для их закачки надо открыть файл, который я пришлю. Так я получала доступ к компьютерам жертв. Могла полностью просматривать жесткий диск, скачивать, что мне надо, удалять с компьютера файлы. Однажды я стала удалять кучу всего с компьютера парня, с которым в это время общалась в чате, и он заплакал. Мне стало жаль его, и я прекратила, и больше никогда этим не занималась.
7. Я занимался этим ради денег. Уже в старших классах я занимался черным СЕО и восстановлением сайтов. Потом я познакомился с парнем, который придумал, как через песню из альбома вшить ссылку. Эта программа случайным образом одну из песен на компьютере превращала в ссылку. Когда человек хотел прослушать ее, всплывала надпись, что надо скачать кодек. Он скачивал, и я получал 10 центов. Свою ссылку мы размещали на торрентах, скачиваний было много, денег хватало. Позже я стал нанимать индусов, чтобы они распространяли по торрентам файл с этой ссылкой. Мне тогда было 16, и я за месяц заработал 4 тысячи долларов. Это было круто, учитывая, что на черном СЕО и сайтах у меня выходило около тысячи в месяц. А через несколько месяцев все пошло наперекосяк, и я стал заниматься другими делами.
Похожие подборки без цензуры и купюр ежедневно выходят на моем канале https://t.me/realhistorys
Всем здоровья и добра!
Показать полностью
Поддержать
10 дней назад

Как понимать мемы про айти?

10 дней назад

3D видеокарта-«декселератор» из 90-х. Как работала S3 ViRGE «под капотом»?

Друзья! Многие ли из вас застали такую легендарную видеокарту, как S3 ViRGE? Когда-то этот GPU стоял чуть ли не в каждом втором офисном компьютере: благодаря дешевизне и заявленной поддержке 3D-ускорения, эту видеокарту просто сметали с полок магазинов. Далеко не все могли себе позволить ATI Rage, Riva TNT и уж тем более 3dfx Voodoo и очень разочаровывались в свежекупленной видеокарте, когда пытались поиграть в новомодные игры тех лет. На момент написания статьи, в сети слишком мало материала о том, как работали видеокарты 90-х «под капотом», однако мне удалось найти даташит на видеочип, SDK для программирования 3D-графики специально под него и некоторую документацию. Я решил исправить это недоразумение и начать развивать отдельную рубрику о работе старых видеочипов: начиная от S3 ViRGE и заканчивая GPU PS2 и PSP. Сегодня мы с вами: вспомним о S3 ViRGE, узнаем о том, как работали видеокарты в 90-х годах, затронем 2D и 3D режим и почему они тесно связаны между собой, посмотрим на проприетарное графическое API S3 ViRGE и раскроем причину, почему же этот GPU был таким медленным!
❯ 3D графика на ПК: начало
В начале 90-х годов 3D-графика на обычных домашних компьютерах была редкостью. Профессиональные GPU применялись только на дорогущих графических станциях, которые использовались в кинематографе или различных симуляциях, а также на дорогих японских игровых автоматах. У простого обывателя не было доступа к аппаратным средствам рендеринга 3D-графики.

Однако это не значит, что 3D-графики не было вообще. Прогресс развития домашних процессоров шёл семимильными шагами и гиганты рынка —Intel,AMDи в некоторой степени Cyrix, выпускали всё новые и новые процессоры с повышенными тактовыми частотами, а ближе к середине 90-х — и с SIMD (MMX). Поскольку многие техники для отрисовки трехмерного изображения были разработаны ещё в 60-х — 70-х годах, игроделы к началу-середине 90-х во всю использовали некоторые наработанные техники из кинематографа для растеризации 3D-графики прямо на процессоре — так называемыйсофтварный рендеринг.

Одной из самых известных техник 90-х являлась 2.5D графика с использованием рейкастинга — когда картинка на экране выглядит как трёхмерная, однако по факту весь мир представлен в виде 2D-координат, а эффект «пола и потолка» был как бы фейковым. Принцип его работы довольно прост: от глаз игрока для каждого горизонтального пикселя (т. е. при разрешении 240х320, у нас будет 240 проходов) пускаются «лучи» и ищется пересечение с ближайшей стеной относительно угла обзор из глаз игрока. Из этого пересечения берется дистанция до этой стены (на основе дистанции и угла считается «высота» данной строчки стены) и считается какую строчку текстуры необходимо вывести в этой точке. Одними из первых игр с применением этой технологии стал Hovertank и Wolfenstein 3D, а технология применялась практически до конца 90-х. Одной из самых лучших реализаций рейкастинга — движок Duke Nukem 3D, Build Engine, написанный Кеном Сильверманом.

Однако не одним 2.5D мы были едины. Шли годы, в СНГ многие люди продолжали наслаждаться 8-битными и 16-битными играми на клонахNESи SMD. У некоторых уже появлялась PS1, которая позволяла играть в игры с довольно хорошей 3D-графикой, однако на ПК 3D-игры были доступны не всем. Но в 1996 году выходитQuake— новейший шутер от первого лица от id Software с настоящей, трушной 3D-графикой и переворачивает всю индустриюFPSс ног на голову. Посудите сами: Джон Кармак умудрился реализовать достаточно быстрый софтварный рендерер, который мог вполне сносно работать на Pentium 75Мгц в разрешении 320x240. А ведь помимо отрисовки кадра, игре нужно было просчитывать логику монстров (довольно примитивную, к слову), обрабатывать столкновения, просчитывать видимую геометрию с помощью BSP-дерева и обрабатывать клиент-серверную логику самой игры. Это была самая настоящая революция в мире 3D игр на ПК.

В 1997 году, id Software выпустили glQuake — порт Quake с софтрендера на OpenGL, плюс своеобразную прослойку для совместимости с API 3dfx Glide (на видеокартах Voodoo) и подмножества OpenGL, используемым в игре. Порт на OpenGL позволял разгрузить ЦПУ, перенеся всю отрисовку графики с процессора на 3D-ускоритель. Сам по себе, OGL как графическое API, представлял из себя лишь набор спецификаций, который мог быть реализован как в программном виде, так и в аппаратном производителем видеокарты (на примере Windows — OpenGL32.dll это программная реализация, которая при необходимости обращается к atioglxx.dll/nvoglvxx.dll — аппаратной реализации OpenGL от вендора видеочипа). Однако, OpenGL корнями уходил именно в отрисовку промышленной графики, а DirectX всё ещё находился в зачаточной форме, из-за чего многие производители разрабатывали собственное графическое API: из известных мне, могу подчеркнуть ATI CIF (C Interface), 3dfx Glide и проприетарное SDK S3 ViRGE. Некоторые вендоры поддерживали целые игровые движки — например, BRender и RenderWare.

Отдельные 3D-акселлераторы потихоньку начали завоевывать сердца геймеров и создавать новый сегмент рынка. Серьезные видеокарты от известных производителей, такие как 3dfx Voodoo, ATI Rage и Riva TNT стоили достаточно дорого и многим были не по карману. Зато существовало множество видеокарт с 3D-ускорителями от других производителей, про некоторые из них вы могли даже не слышать: отдельные дискретные видеокарты Intel (i740), видеокарты от производителя чипсетов SiS и конечно же, видеокарты от S3 с сериями ViRGE и Savage. Видеочипы от Intel и SiS делали упор на D3D 7.

S3 ViRGE была весьма неплохой видеокартой с точки зрения 2D-ускорения. Сейчас 2D принято считать частным случаем 3D (по факту, 2D-спрайты — это 3D-квады, состоящие из двух треугольников), однако в то время для работы с памятью видеокарты и аппаратного ускорения некоторых операций, таких как блиттинг (BitBlt) существовало отдельное графическое API — DirectDraw. С этим у ViRGE было всё хорошо — он поддерживал довольно высокое разрешение экрана (при желании, объём видеопамяти можно было нарастить и установить разрешение ещё выше) и умел ускорять часть операций как DDraw, так и GDI.
Однако, ViRGE разочаровывал многих геймеров 90х своей производительностью в 3D-графике. На коробке с бюджетной видеокартой красовались красивые надписи о 3D-графике следующего поколения, а на фотографии можно было увидеть некую игру про мехов с невиданной графикой!

По факту, ViRGE подходил для 3D-игр не особо хорошо. Конечно в те годы никто особо не плевался от FPS и при желании, игру могли пройти и в 15, и в 20 FPS. Однако производительность софтварного рендерера иногда была даже выше, чем у растеризатора ViRGE, а игры должны были быть специально адаптированы под неё (т. е. портированы для использования S3DTK). Тайтлов с адаптацией по этот GPU было немало: как минимум, Tomb Raider и MechWarrior 2 (который шел в комплекте с игрой). Польские ребята из известной многим Techland даже написали прослойку S3D -> OpenGL, позволявшей запускать Quake на ViRGE. Производительность была не ахти…
Видеокарт от S3 нашлись и у меня, причём сразу несколько — ViRGE в PCI-исполнении и Trio в AGP-исполнении! Иногда я их использую для проверки старых материнских плат, которых у меня не так уж и много — рабочих на PGA370 и ниже у меня совсем нет. Однако остаётся вопрос, как эти видеокарты работали под капотом? Давайте узнаем!
❯ «Под капотом»
Исторически сложилось так, что 3D и 2D акселераторы могли быть отдельными и формально не зависящими друг от друга устройствами. Архитектура IBM PC в зависимости от «поколения», предполагала сразу несколько типов видеоадаптеров, которые были стандартизированы под определенный тип мониторов. Один из таких адаптеров, VGA, стал стандартом на долгие годы, в то время как два других использовались в совсем ранних машинах. Их ключевое отличие было в организации видеопамяти и цветности — CGA/EGA предполагал разбитие пространства экрана на т. н. битплейны (один байт содержал информацию о нескольких пикселях и если не ошибаюсь, для сохранения адресного пространства сегменты экрана необходимо было переключать аля банки памяти) и былпалитровым, в то время как VGA предполагал как палитровый режим, так и полноценный RGB и мог отразить весь фреймбуфер в линейную область адресного пространства. Кроме того, долгое время VGA использовался для обозначения разрешения дисплея: QVGA — половина VGA (320x240), VGA (640x480), широкоформатный WVGA (800x480) и т. п.

Другой особенностью была полная (насколько мне известно) обратная совместимостью друг с другом. Например, GeForce 7xx, как один из последних GPU, который поддерживал Legacy BIOS, теоретически вполне мог работать и с EGA режимами, и с CGA через соответствующие видеорежимы int 10h!
3D-режимы же никак не были стандартизированы и каждый производитель реализовывал работу с ними по разному — как уже говорилось ранее, кто-то реализовывал поддержку совсем молодого D3D и OpenGL (насколько мне известно, лучше всего с OpenGL было у NVidia. Остальные вендоры поддерживали OGL, но были свои болячки — у ATI они тянулись чуть ли не до середины-конца нулевых), а кто-то делал собственное графическое API и работал с видеочипом почти напрямую. Первые 3D GPU использовали шину PCI, которую почти сразу заменила более скоростная, но интерфейсно и софтварно почти идентичная шина AGP, а затем уже появился PCI-E, который оставался тем же PCI в софтовом плане, но был дифференциальным и последовательным, а не параллельным как интерфейсы-предшественники.

Дабы понять, как работают первые видеокарты, необходимо узнать о том, как происходит процесс отрисовки 3D-графики в общем случае. В мире программирования графики это называетсяконвейероми состоит он как минимум из нескольких этапов:
Установка состояний: Программа задаёт источники света на сцене, параметры Z-буфера и Stencil-буфера, какую текстуру(ы) следует наложить на рисуемую геометрию и с какой фильтрацией, какой тип аппаратного сглаживания использовать и т. п.
Ранее, каждый стейт необходимо было устанавливать отдельно, при необходимости — для каждого DrawCall'а. После подготовки состояния, программа вызывает соответствующую функцию отрисовки.
Обработка геометрии: Геометрия не поступает в растеризатор «как есть», в мировых координатах. Растеризатор оперирует вершинами в нормализованныхClip Spaceкоординатах — обычно, это [-1, -1… 1, 1], где 0.5 — центр экрана по каждой оси. Именно поэтому сначала необходимо провести этап трансформации геометрии для перевода из некой глобальной системы координат (которая может выражаться в метрах или, например, в пикселях) в Clip Space. Для этого чаще всего координаты (корректнее — трансформации) представляются в виде трех перемноженных матриц — model (мировые координаты геометрии), view (положение «глаз» в мире, или по простому камера. Умножая model на неё, мы получаем координаты объекта в пространстве камеры) и projection (матрица проекции, которая преобразовывает координаты из пространства глаз в тот самый Clip Space. Именно в этой матрице задается FOV для перспективной проекции и виртуальные размеры экрана для ортографической матрицы). После этого, координаты каждой вершины трансформируются полученной ModelViewProjection матрицей и получается финальная позиция для Clip Space. Звучит как сложный учебник матану, по факту всё очень просто. 🙂

Детали реализации низкоуровневого матана, в том числе перемножения матриц и построения матриц трансформаций и проекции знать желательно, но необязательно. Сейчас этим занимаются очень удобные математические библиотеки — например, glm, dxmath или d3dx.
Кроме того, ранее именно на вершинном этапе считалось освещение для уровня. В некоторых видеочипах была возможность аппаратного расчета источников света, в некоторых — только программная на ЦПУ.
На видеокартах тех лет, в том числе и S3 Virge, трансформацией вершин занимался центральный процессор, из-за чего было довольно серьёзное ограничение на количество вызовов отрисовки и число треугольников в одной модели. Видеокарты с аппаратной, но всё ещё не программируемой трансформацией вершин появились лишь к GeForce 2 — называлась эта технология T&L (Transform and Lightning) и её преимущество было в том, что у видеокарты были специализированные векторные сопроцессоры, способны быстро пересчитывать векторные операции (а у ЦПУ, в свою очередь, развивались SIMD наборы инструкций, позволяющие выполнять несколько операций над float одновременно). В некоторых случаях, был даже отдельный программируемый векторный сопроцессор как, например, в PlayStation 2, что позволяло реализовать вершинные шейдеры ещё в 2000 году! На современных видеокартах, этапом трансформации в самом простом случае управляют вершинные шейдеры. Помимо этого, есть возможность создания геометрии «на лету» с использованием тесселяции и геометрических шейдеров, а совсем недавно появились Mesh-шейдеры, которые объединили несколько подэтапов конвейера в один.

Растеризация: Сам процесс отрисовки геометрии на дисплей с данными, полученными с прошлого этапа. Именно на этом этапе треугольники (или иные геометрические примитивы) закрашиваются определенным цветом или на них накладывается текстура. В процессе растеризации есть такое понятие, как интерполятор — специальный модуль, который интерполирует несколько значений в барицентрических координатах растеризуемого треугольника, дабы текстурный юнит мог наложить определенный участок текстуры на фрагмент треугольника.
В современных видеокартах этот этап конвейера программируется пиксельными (или фрагментными) шейдерами. В старых видеочипах (исключение — вроде-бы частично программируемый GPU Nintendo 64, поправьте в комментариях, если не прав) этот процесс строго определен в каждом GPU и не программировался. Именно поэтому такой подход к рисованию графики назывался Fixed function pipeline. Были ещё комбайнеры, но они появились заметно позже — когда в видеокартах появилось уже несколько текстурных юнитов, способных смешивать несколько текстур одновременно.

Делая вывод, мы можем понять, что S3 Virge и другие видеочипы были устройствами, которые умели рисовать лишь тот уровень графики, который был заложен производителем с завода. Такой подход называется фиксированным конвейером — Fixed Function Pipeline. Сейчас разработчики видеочипов перешли с фиксированного конвейера на программируемый (шейдерный). Уже начиная с SM2.0-SM3.0, на современных видеокартах появилась возможность создавать крутое и достаточно сложное освещение и различные эффекты, которые стали неотъемлемыми в современных играх.
Кроме того, важно понимать, что в видеопамяти ранних видеочипов хранился только фреймбуфер, а немного позже — текстуры, именно поэтому VRAM в старой документации называют «текстурной памятью». Вообще, некоторые нюансы первых версий OpenGL тянуться именно из особенностей работы первых видеокарт. Вспомнить хотя бы первые функции для старта отрисовки геометрии и загрузке вершин на видеокарту — это были связки glBegin/glVertex/glEnd:
glBegin(GL_TRIANGLES);
glVertex3f(0, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(1, 1, 0);
glEnd(); // Для одного треугольника
glBegin(GL_TRIANGLES);
for(int i = 0; i
glEnd(); // Для меша
Даже сам glBegin/glVertex/glEnd появились не спроста. Геометрию на видеокарте начали хранить только в начале нулевых (и то не везде — привет встройкам Intel и S3).
Но перейдем к особенностям работы S3 ViRGE. Даташит лежит в свободном доступе, благодаря чему мы можем более подробно ознакомиться с характеристиками этого видеочипа и о том, как он работал под капотом.

В основе у нас лежит 64-х битное ядро, которое могло обрабатывать как 2D-графику с аппаратным ускорением, так и 3D-графику. Ядро работало на частоте 135МГц с встроенным RAMDAC (модуль, отвечающий за вывод картинки на аналоговые разъемы — VGA и DVI, однако выводом на TV-тюльпаны занимался отдельный чип TV-энкодер). Современные видеочипы перешагнули планку 1ГГц, однако сравнение исключительно по частоте некорректны — архитектуры очень сильно отличаются. Помимо этого, видеочип умел декодировать видео с интерполяцией и аппаратно «помогать» процессору с скейлингом видео (например, когда вы разворачиваете плеер на весь экран) и даже рендерить видео в текстуру (что позволяло реализовать, например, телевизоры в играх)!
3D движок поддерживал следующие возможности:
- Затенение по Гур.о
- Маппинг текстур с перспективной коррекцией и билинейной/трилинейной фильтрацией, а также мипмаппингом.
- Depth-буфер, сэмплинг тумана и поддержка альфа-блендинга (прозрачной геометрии).
Чип поддерживал две шины — PCI и менее известную VLB (Vesa Local Bus, очень условно ISA)
Помимо этого, у чипа не было встроенной памяти — к нему необходимо было подключать внешнюю DRAM-память 2/4/8Мб. От её количества зависело максимально-поддерживаемое разрешение экрана. Текстуры при необходимости хранились в ОЗУ.

Видеопамять когда-то расширялась за счёт дополнительных модулей! Эту видеокарту можно расширить аж до 8МБ!
Поддерживаемые разрешения экрана:

Для DirectDraw и ускорения 2D-графики в Windows была реализация аппаратного BitBLT — копирования пикселей в точку на экране. Она поддерживала все режимы, которые были в реализации этой функции в Windows — от монохромных, до 24-х битных. Без альфа-блендинга, само собой. Но тут нет ничего необычного — многие видеочипы тех лет предоставляли простое 2D-ускорение.
Интереснее реализация отрисовки 3D-графики. Каждый треугольник описывался 3-мя регистрами на каждый параметр — координата X, Y для каждой точки, текстурные координаты и т. п. Всего для отрисовки одного треугольника могло потребоваться до 43 регистров! Весьма немало. И именно из-за этого в свое время появились glBegin/glVertex/glEnd!

Параметры сэмплера (текстурного юнита) задавались регистрами, которые определяли формат пикселя текстуры и сам тип фильтрации. Как я уже говорил выше — поддерживалась билинейная и трилинейная фильтрация и проприетарный формат сжатия текстур, который стал стандартом: S3TC или DXT.

Для программирования S3 ViRGE было разработано собственное C SDK — S3DTK, которое состояло из сэмплов и заголовочных файлов для общения с GAPI видеочипа (или видеочипом напрямую, если игра предназначена для DOS). При этом вполне не исключено, что GAPI для Windows работало с видеокартой напрямую, предоставляя PCI-драйвер лишь как прослойку для обмена данными. Поскольку это не D3D, для игр с поддержкой видеоускорения требовалось качать специфические версии. Некоторые игры (как Quake 2) поддерживали мультирендер, но не поддерживали S3 ViRGE.
Весь графический API помещался в один заголовочный файл. API было не простым, а очень простым и понятным — думаю, даже разработчикам-новичкам было легко начать программировать под ViRGE!

Формат вершин был фиксированным и зависел от того, как вы рисовали геометрию на экране:

GAPI поддерживало различные типы треугольных списков, а также точки (POINT для спрайтов и систем частиц) и линии:
#define S3DTK_TRILIST 0
#define S3DTK_TRISTRIP 1
#define S3DTK_TRIFAN 2
#define S3DTK_LINE 3
#define S3DTK_POINT 4
Фактическое API для рисования умещалось в 9 функций и ещё несколько функций для инициализации библиотеки, преобразования адресного пространства и работы с Windows.
Для работы с состоянием видеочипа служили две функции — SetState и GetState. Именно они отвечали за то, как рисовалась геометрия на экране:

А для фактического рисования примитивов служили функции TriangleSet и TriangleSetEx! Да, это альтернатива DrawPrimitives/DrawArrays в современных GAPI. Никаких индексов тогда ещё не использовалось! Функции принимали указатель на массив вершин и их количество, а также на тип рисуемой геометрии (треугольники, линии и т. п.). В Ex версии, можно было «пачкой» установить стейты параллельно с рисованием — такой подход используется в DX10+ API — стейты тоже задаются исключительно «пачками», только теперь они поделены на подгруппы.

Для 2D-рисования были свои, отдельные функции — для блиттинга. Поддерживался ColorKey/хромакей — прозрачным считался определенный цвет, переданный как параметр функции

Основной причиной медлительности S3 ViRGE был низкий филлрейт. При отрисовке примитивов, которые занимают большое пространство экрана, FPS резко просаживался даже с примитивными кубиками и пирамидками. Однако, если не насаживаться на филлрейт и делать что-то типа 2D-поля и 3D-танчиков, то производительность оставалась вполне приемлимой.
❯ Заключение
История S3 закончилась поглощением компанией VIA. После этого, компания разрабатывала интегрированную графику специально для чипсетов VIA, а материнские платы на этих чипах пользовались довольно высоким спросом. Поэтому нередко взяв старый бюджетный ноутбук, года эдак 2005, можно найти в нём VIA Chrome — наследника легендарного S3 Savage! Проблемы у такого подхода тоже были — из-за наследия из конца 90х, ранние Chrome по сути поддерживали только D3D 7.0 и OpenGL ~1.4. Несколько позже, в 2009 году, компания выпустила S3 Chrome 540 GTX — одну из последних видеокарт на собственной архитектуре. Этот видеочип был достаточно современным и поддерживал DX10.1, OpenGL 3.0. Интересно, реально ли найти эту видеокарту сейчас?

По итогу мы можем сделать вывод, что первые 3D-ускорители были относительно простыми устройствами «под капотом» и их можно было программировать чуть ли не «напрямую». Многие старые видеочипы получили свои локальные прозвища и стали легендарными, однако их архитектура и принцип работы оставались тайной. По крайней мере, в рунете точно.

Насколько я понимаю, неравнодушные инженеры после закрытия 3dfx и слияния S3 с VIA решили «слить» даташиты в сеть, за что им большое спасибо! Ведь теперь мы имеем возможность посмотреть на принцип работы таких устройств сами!
Материал подготовлен при поддержке TimeWeb Cloud. Подписывайтесь на меня, мой Telegram и @Timeweb.Cloud, чтобы не пропускать новый материал каждую неделю!
Показать полностью 24
Поддержать
12 дней назад

А сеньор знает толк в извращениях.

15 дней назад

Нужна срочно помощь, боюсь моя мама стала дропом (жертвой мошенников)
Здравствуйте. Пишу анонимно, очень нужна помощь знающих. Сейчас позвонила мама, сказала, что устроилась на курьером. Заплатили большие деньги даже для Мск, 5 тыс. за отвоз документов в налоговую и банки.
Сказала, что по приезду ей оформили ЭЦП (электронную цифровую подпись) по СНИЛС и паспорту. Подпись квалифицированная (подписанные Эл. документы имеют силу оригинала) Отвезла документы, поставила Эл. подпись (с помощью) флешки в накладных. Подпись выдал Такском, Такском сказал, что при оформлении ЭЦП была указана почта в виде номера телефона (не мамин тел.)
Но меня все равно настораживает, что:
– Юр. фирма Corp или Comp Pro, не могу найти
– Попросили сделать фото факта доставки, менеджер попросил удалить фото
– Зачем курьеру юр. фирмы ЭЦП, как это ставится в накладных?
– Мама сказала, что оформили по договору ГПХ, но деньги заплатили сегодня на карту переводом.
Может я зря паникую? Ничего не понимаю. Пожалуйста, помогите!
15 дней назад
Помогите советом как закончить отношения с потенциальным суицидником
Уважаемые пикабутяне, взываю к силе Пикабу!
Прошу совета, сам не выгребаю.
Предыстория.
Почти 4 года назад начал встречаться с девушкой. На первом же свидании мы провели ночь вместе, переспали. Дальше, почти каждый день мы ночевали вместе в гостиницах или съёмных квартирах. Я тогда ещё начал замечать жёсткий абьюз и манипуляции. Но это были первые серьёзные отношения и я не совсем вдуплял что это плохо и что это "звоночки". Спустя месяц мы познакомились с родственниками друг друга. Потом бахнула первая волна ковида и так получилось, что на самоизоляции мы оказались вместе. Как кончился карантин почти сразу съехались. Она много рассказывала какое трудное детство у неё было. Как мать ругала её или наказывала молчанием. Как бедно они жили, мол, у них часто на обед/ужин был только хлеб с чаем. Как ей не хватало отца, потому что они с мамой сбежали от него (со слов мамы он был алкаш, но она ни разу не помнила его пьяным). Как в школе комплексовала из-за того, что из бедной семьи. Как родственники отвернулись от них. В общем, очень много плохого из своего детства рассказала. Я, наслушавшись всего этого, просто не мог отказать ей в каких-то её капризах и часто сам по своей инициативе что-то ей покупал. Она не работала около полугода. Потом нашла работу оператором на телефоне за символическую ЗП. Жили на мою ЗП и меня искренне это не парило. У неё не было хобби или близких друзей. Я предлагал ей разные хобби, но она бросала спустя пару недель. Каждый вечер мы проводили вместе. Если я ехал к друзьям или родственникам, она оставалась дома и когда я возвращался, то сначала демонстративно обижалась, а потом устраивала скандал. Я звал её с собой. Но она говорила, что ей некомфортно с моими родными/друзьями. У неё с её родными очень натянутые отношения. С мамой ругаются часто и могут по несколько недель не разговаривать. Её мама может сказать ей ооооочень обидные вещи, сам был свидетелем. А она маму любит, искренне, но не всегда может терпеть её характер. Ещё у неё есть сестра, но у них разные отцы и эта сестра последние лет 5 стала к ней очень холодно относиться.
Из своих "косяков" я бы отметил что я очень интровертный, я редко выхожу куда-то, примерно, раз в 2 недели. Ей хотелось гулять со мной каждый день. Из-за этого часто ссорились. Ещё я скуп на слова. Я свои чувства проявляю через действия. Ей же хотелось больше тёплых слов. Ещё, мне не всегда хотелось секса, потому что я тупо уставал на работе. Работа не физическая, но я работал в отделе за 3 без преувеличений.
Многое ещё можно рассказать о наших отношениях, не знаю что из этого будет полезно для понимания картины.
В прошлом году она, не сказав мне, начала брать микрокредиты и на эти деньги покупать одежду, всякие вещи в дом (типа всяких вазочек, ароматизаторов и прочей приблуды для уюта), ездить на работу на такси, обедать в кафе или доставку заказывать, по вечерам не готовить, а заказывать что-нибудь. Сначала я не замечал. Потом спросил. Она сказала, что на работе получает процент за каждого привлечённого клиента. Когда всё всплыло, она уже должна была очень крупную сумму, там было 12 микрокредитов. Я стал отдавать все "свободные" деньги на эти долги. Получил бонус за самую крупный проект в своей карьере, все деньги отдал ей на долги, закрыли почти всё. Спустя какое-то время она снова в тайне от меня начала брать кредиты. Мы стали жить реально впроголодь.
В какой-то момент нам тупо не хватило денег на квартплату и мы разъехались.
Расстались в начале августа.
Для себя я определил главные причины - микрокредиты, её истерики на пустом месте, оскорбления во время ссор (дважды было рукоприкладство с её стороны. Я никогда руку не поднимал на неё и голос не повышал, не матерился ни разу) и потерю симпатии к ней, как к девушке (набрала около 20кг).
Сначала всё было ок. В день расставания она поплакала, но потом просто ушла.
Спустя пару дней написала огромное сообщение о том, какая у неё крутая жизнь без меня. Я ответил ей что рад за неё, желаю только хорошего и всё в таком духе. Спустя ещё пару недель она написала что ей плохо, всё ещё любит и хочет возобновить. Я отказал. Потом она предложила просто общаться как друзья, мол, ей очень помогает моя рациональность и холодная голова, хочет советоваться со мной иногда (она тогда запустила мини-бизнес по перепродажи товаров с Китая). Я согласился. Спустя какое-то время она начала напирать с предложением продолжить отношения. В прямом смысле домогалась меня сексуально. Когда я пытаюсь выстроить личные границы (типа "не звони мне чаще 2 раз в неделю" или "не приезжай ко мне без предупреждения"), её клинит, она начинает истерить звонит мне по 20-30 раз, пишет в Ватсапп кучи сообщений. В конце начинает говорить что жить ей больше нет смысла. Меня это пугает. В этот момент я ломаюсь и начинаю говорить ей слова поддержки. Таких эпизодов за 2 месяца было около 5-7. В одном из случаев она скидывала мне фото как она идёт в бизнес-центр, где у неё офис на 16 этаже и открывающееся окно, и пишет что спрыгнет. В другой раз звонит по видеозвонку с крыши какого-то здания. Однажды, когда я пришёл к ней в гости (она звонила в 4 утра, говорила что боится спать одна в новой квартире, начинала истерить) и отказался оставаться ночевать, она закатила истерику, сказал что умрёт если я уйду. Я ушёл. Когда выходил с подъезда, она позвонила и сказала что держит в руке нож. Я испугался. Вернулся. Она реально сидела с ножом в руке. Я начал идти к ней, она заорала на меня и сказал чтоб я ушел. Я психанул, развернулся и ушёл. Написал её матери чтоб позвонила ей. Её мать и сестра не верят что она сделает что-то с собой. Сама девушка говорила что в подростковом возрасте однажды пыталась убиться.
Я головой понимаю что за её действия я не несу никакой ответственности. Но мне эмоционально очень тяжело в такие моменты. У меня из-за этих переживаний начались проблемы на работе. Очень плохо сплю. Я не могу войти в новые отношения, хотя есть другая девушка, которая очень нравится, у нас взаимная симпатия, но я очень боюсь реакции бывшей на то, что у меня новые отношения.
Пожалуйста, помогите советом как безопасно для неё, в первую очередь, прекратить это общение.
Пробовал постепенно снижать количество общения, но это не помогает, она срывается и снова случается эта манипуляция суицидом.
Она несколько раз пробовала заниматься с психологом, но дальше 2-3 сеансов не двигается процесс. Она говорит что они какие-то не такие и бросает. Уже 4-5 специалистов сменила.
Я устал. Очень устал. Морально и эмоционально разбит. Я не знаю что делать и как выбраться из этого болота.
Installing the AWS Toolkit for Visual Studio Code
To get started working with AWS Toolkit for Visual Studio Code from VS Code, the following perquisites must be met. To learn more about accessing all of the AWS services and resources available from the AWS Toolkit for Visual Studio Code, see the Optional prerequisites section of this guide.
- VS Code requires a Windows, macOS, or Linux operating system.
- The AWS Toolkit for Visual Studio Code requires you to work from VS Code version 1.42.0 or a later version.
For additional information about VS Code or to download the latest version of VS Code, see the VS Code downloads website.
Downloading and installing the AWS Toolkit for Visual Studio Code
You can download, install, and set up the AWS Toolkit for Visual Studio Code through the VS Code Marketplace in your IDE. Alternatively, you can download the AWS Toolkit for Visual Studio Code installation files by navigating to the VS Code Marketplace from your web browser.
Installing the AWS Toolkit for Visual Studio Code from the VS Code IDE Marketplace
- Open the AWS Toolkit for Visual Studio Code extension in your VS Code IDE with the following link: Open the VS Code Marketplace .
Note
If VS Code is not already running on your machine, this operation may take a few moments while VS Code is loading.
Optional prerequisites
Before you can use certain features of the AWS Toolkit for Visual Studio Code, you must have the following:
- Amazon Web Services (AWS) account: An AWS account isn't a requirement to use the AWS Toolkit for Visual Studio Code, but functionality is significantly limited without it. To obtain an AWS account, go to the AWS home page . Choose Create an AWS Account, or Complete Sign Up (if you've visited the site before).
- Code Development – The relevant SDK for the language that you want to use. You can download from the following links, or use your favorite package manager:
- .NET SDK: https://dotnet.microsoft.com/download
- Node.js SDK: https://nodejs.org/en/download
- Python SDK: https://www.python.org/downloads
- Java SDK: https://aws.amazon.com/corretto/
- Go SDK: https://golang.org/doc/install