Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   псевдо 3D - как сделать освещение? (http://www.flasher.ru/forum/showthread.php?t=123087)

DRAGOnoid 24.03.2009 15:57

псевдо 3D - как сделать освещение?
 
здравствуйте ещё раз. Развивая тему 3Д решил попробовать сделать ещё освещение.
как я полагаю делается за счёт поиска угла между вектором нормали к плоскости и вектором самого света...

посему вопрос - как найти нормаль к плоскости в пространсвте?

единственное до чего додумался это что можно получить гломальную матрицу с помощью getRelativeMatrix3D
а что дальше с ней делать - ума не приложу :(
ведь чтобы получить хотя бы нормаль с помощью Vector3D.crossProduct - надо знать 2 вектора лежащие на плоскости.

а может вообще есть способ по проще, организовать затемнение или засветление объекта?

Alex Lexcuk 24.03.2009 17:08

>>Развивая тему 3Д решил попробовать сделать ещё освещение.
Правильно.
Делать можно так: Брать желательно среднюю точку грани, или если объект разбит на мелкие грани любую точку грани. В общем
Код:

var грань:Vector3D = new Vector3D(100,100,100);
var солнышко:Vector3D = new Vector3D(1000,1000,1000);
var свет:Number = Vector3D.distance(грань,солнышко);

Если солнышко будет далеко, то эффекта 0. Если близко то тоже 0;
Суммируя выше сказанное эффект 0, отсюда следует, что данный способ не подходит. Легче всего не напрячь процессор и получить красиво задумманое это просто сделать интервал дистанци для каждого объекта в отдельности и нафик этот свет, если он так далеко, то можно сделаь свет слева, свет справа или свет спереди или сзади.
В общем вот пример простого самодельного света. (свет спереди нагрузка на проц минимум)
http://www.murmadillo.tut.su/html/4cube.html

>>посему вопрос - как найти нормаль к плоскости в пространсвте?
>>ведь чтобы получить хотя бы нормаль с помощью Vector3D.crossProduct - надо знать 2 вектора лежащие на плоскости.

Ну так вы их знаете первый вектор это ваш свет, а второй это ваша плоскость.

DRAGOnoid 24.03.2009 17:28

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

в общем всё сводится к тому - как найти вектор нормали к плоскости по её Matrix3D.

Alex Lexcuk 24.03.2009 17:35

Вложений: 2
>>в общем всё сводится к тому - как найти вектор нормали к плоскости по её Matrix3D.

Никак. Matrix3D - это просто преобразования к плоскости можно и к вектору матрицу применить.

сслка что то у меня неработает

А я не удивляюсь, это ж бесплатный хостинг, я и платный юзал, то-же самое бывает что он не работает.

_dm 24.03.2009 18:13

Цитата:

Ну так вы их знаете первый вектор это ваш свет, а второй это ваша плоскость.
Как это плоскость может быть вектором? О_о
Да и вектор, который свет, не подходит, потому что он не лежит на освещаемой плоскости.

DRAGOnoid
А зачем тебе плоскость освещать? Треугольников у тебя разве нету?

Цитата:

в общем всё сводится к тому - как найти вектор нормали к плоскости по её Matrix3D.
это смотря как плоскость размещена БЕЗ трансформации. Если, допустим, это XZ, ZY, ZX плоскость, то можно. Нормалью будет один из столбцов(строк) матрицы.

А вобще данных мало... Откуда у тебя плоскость, если ты не знаешь её нормали. И как ты применяешь трансформации к плоскости если у тебя, опять же, нету её нормали? Это ж невозможно =)

Alex Lexcuk 24.03.2009 18:45

>>Как это плоскость может быть вектором? О_о

А почему плоскости не быть вектором. Вы ж представляете себе плоскость. Это такая плоская здоровенная штуковина которая может лежать на трех точках одновременно. У первой точки могут быть координаты (100,0,0) у второй (0,100,0) и третья (0,0,100). Те. это вектор (100,100,100). Таким образом можно одним вектором описать любую плоскость. И найти методом
Код:

crossProduct(a:Vector3D):Vector3D
Возвращает новый объект Vector3D, который расположен перпендикулярно (под прямым углом) к текущему и второму объекту Vector3D.

Перпендикуляр к этим плоскостям.

DRAGOnoid 24.03.2009 18:50

плоскость я вращаю за счёт встроенных вращений во флеше типа rotationY

как применить к Vector3D - Matrix3D ?

litebox 24.03.2009 19:09

Есть такое понятие: плоскость, и есть такое понятие: вектор; вектор != плоскость, это факт :)
По поводу самодельных трехмерных движков, есть такая книга http://www.ozon.ru/context/detail/id/1692806/ - вариант для C, но там очень много теоретического материала по созданию, освещению и текстурированию 3d моделей - автор свое дело знает :)

Яски 24.03.2009 19:54

Какая куча бреда в отдельно взятой теме.

Плоскость можно задать многими способами, один из них это нормаль(вектор) и оффсет(число).

Как я понял вы хотите сделать освещение по Ламберту — каждая грань будет освещена равномерна по всей площади, свет имеет направление, но не имеет координаты.
Тогда формула освещенности для каждой грани будет такой:
Код:

  intensity = dot(normal, light) + ambient
    dot — скалярное произведение векторов
    normal — нормаль грани
    light — направление света
    ambient — любое число, значение освещенности "по-умолчанию".

Дальше нам нужно получать нормаль грани. Я, если честно, пока еще не разбирался с работой с 3D в десятке, и, например не знаю, как там расположены оси координат. Вижу пока два способа получения нормали экранного объекта( это вектор перпендикулярный плоскости объекта)
Код AS3:

 //для начала получаем глобальную матрицу
 var matrix:Matrix3D = dsp.getRelativeMatrix3D(stage);
 // Получаем вектор нормали в глобальном пространстве, здесь два варианта — преобразуем из локальных координат одну из осей или получаем компоненты этих векторов прямо из матрицы.
  // По первому способу, передаем локальную ось z (может правильно будет передавать и другую ось, могу ошибаться, это зависит от конкретной реализации, вобщем ось вверх
  var normal:Vector3D = matrix.deltaTransformVector(Vector3D.Z_AXIS);
  // Свет направлен вертикально вниз по оси z
  const light:Vector3D = new Vector3D(0, 0, -1);
  var intensity:Number = light.dotProduct(normal) + 0.1;
  // При использовании этого способа экранный объект нельзя масштабировать, иначе результат будет неправильным. Для учета масштабов есть еще один способ.


Alex Lexcuk 24.03.2009 20:14

>>как применить к Vector3D - Matrix3D ?

Да, мой исходничек не смотрели, ладно, я сейчас сам посмотрю, кстати по свой же ссылке
Код:

_pVec = mat3D.transformVector(_pVec);
И вот так считается свет до камеры (по координате Z) красиво и не дорого (экономия процессора)
Код:

//работает только красный (для примера)
                public function calcColor(_color:uint,_dist:Array,_index:int):uint{
                        var color:uint;
                        len = _dist.length;
                        var dMin:Number = _dist[0][0];
                        var dMax:Number = _dist[len-1][0];
                        var dStep:Number = Math.abs((dMax - dMin)/len);

                        var rMin:uint = 0x00;
                        var rMax:uint = 0xee;
                        var cStep:Number = Math.abs((rMin-rMax)/len);

                        var r:uint;
                        var g:uint = 0x00;
                        var b:uint = 0x00;



                        var ind:Number = (_dist[_index][0]-dMin)/dStep;
                        r = uint(rMax-cStep*ind);
                        color = ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
                       
                        return color;
                       
                }

>> вариант для C
Смотрел варианты для С или С++. Флеш им не конкурент. Ибо большая чать, того что мы тут пытаемся сделать внедрена в видуху в виде OpenGl и тени и свет и сортировка граней и многое прочее выполняется в видеокарте, и там ничего химичить не надо - оно идет само собой. Так что С пока пусть полежит в сторонке.

VVall 24.03.2009 20:28

Цитата:

Сообщение от Alex Lexcuk (Сообщение 808289)
Смотрел варианты для С или С++. Флеш им не конкурент. Ибо большая чать, того что мы тут пытаемся сделать внедрена в видуху в виде OpenGl и тени и свет и сортировка граней и многое прочее выполняется в видеокарте, и там ничего химичить не надо - оно идет само собой. Так что С пока пусть полежит в сторонке.

Видеокарты с аппаратной поддержкой 3D были не всегда, как и мощные процессоры. Читайте старые книги и статьи. Здесь есть кое-что.

Яски 24.03.2009 20:41

Alex Lexcuk, я скажу вам печальную весть, мужайтесь — у вас поражен мозг. Да, да я точно знаю (я смотрел Доктора Хауса).
Да, Си и Си++ имеют аппаратную поддержку многих вещей, но это не значит, что некоторые алгоритмы не подходят и для флеш (все-таки аппаратная подержка была не всегда), здесь сложно придумать что-то свое, лучшее.
Не люблю цепляться к словам, но не говорите того, чего не знаете.
Цитата:

внедрена в видуху в виде OpenGl
OpenGl предоставляет стандартный интерфейс для приложений, затем передает выполение команд драйверу видеокарты.
Цитата:

и тени
Стандартного (обобщеного) алгоритма построения теней нет. (если это, конечно не RayTracing, там все по-тупому и отражения и тени). На аппаратном уровне только есть возможность использования наиболее популярных алгоритмов.
Цитата:

и свет
Правда, свет есть.
Цитата:

и сортировка граней
Сортируют в редких случаях (прозрачные объекты, различные оптимизации) ито на процессоре.
Цитата:

оно идет само собой
Само собой ничего не бывает.

Alex Lexcuk 24.03.2009 23:32

>>внедрена в видуху в виде OpenGl
Чего вы спорите???
На столе лежит книжеца (старая) и в ней написано:
Быстродейтвие программ использующих OpenGL, существенно зависит от видеоадаптера. Аппаратная реализация всех базовых функций OpenGL - залог высокого быстродействия.
Драйвер для видеокарты конечно должен быть установлен, как-же без него-то.
У меня когда я эту книгу читал был Пентиум 233Мгц и видуха с 1.5 мГб памяти - OpenGL работал.
http://www.murmadillo.tut.su/m/Snap2.jpg
и сортировка граней

>>Сортируют в редких случаях (прозрачные объекты, различные оптимизации) ито на процессоре.
Ну это вы уже погнали волну...
>>и тени
>>Стандартного (обобщеного) алгоритма построения теней нет.
Тени уже есть... Где-то видал как их делать (но, забыл). Можно почитать и узнать.
http://gamedev.ru/articles/?id=20121
В общем все работает само-собой вот затестил только что. Код полностью непригодный для флеша
Код:

//------------(c) Copyright Порев В.Н-------------
void myGlStart(HDC hdc)
{
        //hdc = Canvas->Handle;
        HGLRC hglrc;
        PIXELFORMATDESCRIPTOR pfd;
        int iPixelFormat,i,j;

        memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
        pfd.nVersion = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.cColorBits = 24;
        pfd.cDepthBits = 32;
        pfd.iLayerType = PFD_MAIN_PLANE;
        iPixelFormat = ChoosePixelFormat(hdc, &pfd);
        SetPixelFormat(hdc,iPixelFormat,&pfd);
        hglrc = wglCreateContext(hdc);
        if (hglrc)
                wglMakeCurrent(hdc, hglrc);

        float nx,ny,nz;
        GLfloat lightpos[4] = {3,3,4,1};
        GLfloat lightdirection[3] = {-0.5,-0.6,-0.7};
        //gluOrtho2D(-400,400,-300,300);
        //gluOrtho2D(4,4,-4,4);
        glClearColor(1.0f,1.0f,1.0f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glClearDepth(1.0);
        glEnable(GL_DEPTH_TEST);
        //ракурс показа
        gluPerspective(50,double(550/400),1,40);//-400,400,-300,300);

        glMatrixMode(GL_MODELVIEW);//видовая матрица

        //glLoadIdentity();
        glTranslatef(0,0,-10);
        glRotatef(27,1,0,0);
        glRotatef(-19,0,1,0);
        //ЗАДАЕМ ПАРАМЕТРЫ ИСТОЧНИКА СВЕТА
        glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
        glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdirection);
        glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,4);
        glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,50);
        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);
        glEnable(GL_COLOR_MATERIAL);
        glEnable(GL_NORMALIZE);

        //рисование пирамиды

        glColor3f(1,1,0);
        NormalVector(&nx,&ny,&nz,
                        0,4,0,
                        2,0.7,2,
                        2,0.7,-2);
        glNormal3f(nx,ny,nz);
        glBegin(GL_TRIANGLES);
        glVertex3f(0,4,0);
        glVertex3f(2,0.7,2);
        glVertex3f(2,0.7,-2);
        //передняя грань
        NormalVector(&nx,&ny,&nz,
                        0,4,0,
                        -2,0.7,2,
                        2,0.7,2);
        glNormal3f(nx,ny,nz);
        glBegin(GL_TRIANGLES);
        glVertex3f(0,4,0);
        glVertex3f(-2,0.7,2);
        glVertex3f(2,0.7,2);
        glEnd();
        //----------рисуем шахматное поле
        glNormal3f(0,1,0);
        for (j=-5;j<5;j++)
                for (i=-5;i<5;i++)
                {
                        if ((abs(i+j)%2)==0)
                                glColor3f(1,0,0);
                        else
                                glColor3f(1,1,1);
                        glBegin(GL_QUADS);
                        glVertex3f(i,0,j);
                        glVertex3f(i+1,0,j);
                        glVertex3f(i+1,0,j+1);
                        glVertex3f(i,0,j+1);
                        glEnd();
                }
        glFinish();
}


Stargazer 25.03.2009 00:05

Цитата:

Чего вы спорите???
На столе лежит книжеца (старая) и в ней написано:
В самой видеокарте OpenGL нет. Точно так же, как в процессоре нет C++. Думаю, такая аналогия будет понятна.

Фраза в книжке правильная. Но из неё не следует, что любая видеокарта поддерживает OpenGL. Конкретно ваша полутораметровая видеокарта, почти наверняка, работала в программном режиме (рассчёт производился центральным процессором).

Яски 25.03.2009 00:50

Цитата:

Сообщение от Alex Lexcuk (Сообщение 808327)
>>Сортируют в редких случаях (прозрачные объекты, различные оптимизации) ито на процессоре.
Ну это вы уже погнали волну...

Ну как бы в видюхе используется z-буффер, при отрисовке полигона, ищется расстояние от экрана до каждого пикселя и проверяется со значением в буффере. После отрисовки получается корректное перекрытие полигонов, для непрозрачных полигонов сортировка не нужна. С прозрачными полигонами есть проблема в том, что они могут перекрывать друг друга, значит их нужно рисовать в определенном однозначном порядке для правильного смешивания.
Цитата:

>>и тени
>>Стандартного (обобщеного) алгоритма построения теней нет.
Тени уже есть... Где-то видал как их делать (но, забыл). Можно почитать и узнать.
Это один из сотни способов построения теней.

Stargazer 25.03.2009 01:04

Цитата:

для непрозрачных полигонов сортировка не нужна
Это вопрос интересный. Разве не нужна? А каким образом тогда определяются невидимые плоскости (которые видеокарта не рисует)? Я даже знаю, что для определения относительного положения плоскостей используется механизм с двоичным деревом. Может быть, это и не относится к z-буферу, но всё равно получается, что сортировка происходит.

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

Яски 25.03.2009 11:14

Если есть z-буффер, сортировка не нужна. В z-буффер можно рисовать полигоны в любом порядке, результат всегда будет один. Перед отрисовкой отсекаются повернутые задом к экрану полигоны, во время отрисовки отсекаются части за экраном. Затем происходит проверка по z-буфферу.

litebox 25.03.2009 11:52

Цитата:

>> вариант для C
Смотрел варианты для С или С++. Флеш им не конкурент. Ибо большая чать, того что мы тут пытаемся сделать внедрена в видуху в виде OpenGl и тени и свет и сортировка граней и многое прочее выполняется в видеокарте, и там ничего химичить не надо - оно идет само собой. Так что С пока пусть полежит в сторонке.
Alex Lexcuk, книга, что я вам советовал на первой страничке, написана для того, чтобы самостоятельно написать software-рендерер, а это значит, что ни OpenGL, ни Direct3D там не используются; используется много математики, тригонометрии и DirectDraw для растеризации, что в вашем случае отлично подходит, только DirectDraw заменяется на векторные элементы или BitmapData

undefined 25.03.2009 15:07

2 DRAGOnoid: матрица преобразования содержит координаты нормали, т.к. состоит она из проекций ортов i,j,k мувика на глобальный stage. MovieClip к этим ортам жестко привязан и лежит всегда в плоскости ij, следовательно нормаль к нему = k, а k - это третья строчка матрицы преобразования, т.е, учитывая что матрица имеет размеры 4x4:
Код AS3:

n.x = mc.transform.matrix3D.rawData[8];
n.y = mc.transform.matrix3D.rawData[9];
n.z = mc.transform.matrix3D.rawData[10];


DRAGOnoid 25.03.2009 19:26

Цитата:

Сообщение от undefined (Сообщение 808459)
2 DRAGOnoid: матрица преобразования содержит координаты нормали, т.к. состоит она из проекций ортов i,j,k мувика на глобальный stage. MovieClip к этим ортам жестко привязан и лежит всегда в плоскости ij, следовательно нормаль к нему = k, а k - это третья строчка матрицы преобразования, т.е, учитывая что матрица имеет размеры 4x4

СПАСИБО! я уже и не надеялся услышать дельный ответ - завтра попробую поэкспериментировать =)))

кстати Z буффер бы флешу реально бы не помешал так как сортировать там 3 плоскости образующие тип рельсы - крааайе проблемотично.

Яски 26.03.2009 01:19

После задания scale'ов длина вектора будет неправильной.

undefined 26.03.2009 02:08

я склоняюсь к мысли, что если это и произойдет то оч. нескоро т.к. введение сортировки по глубине (или z-буфера или любого другого способа определения очередности отрисовки) отменит слои (и глубины) в flash IDE что превратит редактор в мини-3dmax с последующей эволюцией в 3dmax, видимо поэтому 3д в 10-ке называют "3д трансформациями"
П.С.:
в принципе z-буфер во флэше сделать можно, даже на as2
http://www.free-lance.ru/users/rfc/v...p?prjid=805813

Добавлено через 1 минуту
2 Яски:
главное не длина - главное направление.

Яски 26.03.2009 03:18

ну и направление тоже, если скалировать по осям по-разному.

Где-то видел движок с z-буффером, с графикой типа кваки первой.

VVall 26.03.2009 03:46

Z-буфер сделать очень легко, даже по сравнению с простейшей сортировкой полигонов. Но без аппаратного ускорения он будет работать медленно, тем более если растеризатор написан на интерпретируемом языке.

undefined 26.03.2009 04:41

2 VVall: ну с чего ты взял? квака2 на p233 без аппаратной поддержки летает вполне сносно и там есть z-буфер.
Цитата:

тем более если растеризатор написан на интерпретируемом языке
именно поэтому не надо писать растеризатор на интерпретируемом языке, лучше использовать растеризатор встроенный в этот язык.

VVall 26.03.2009 05:28

Цитата:

Сообщение от undefined (Сообщение 808639)
2 VVall: ну с чего ты взял? квака2 на p233 без аппаратной поддержки летает вполне сносно и там есть z-буфер.

Ну раз я про это пишу, то взял с собственного опыта, наверное? Будете утверждать, что растеризация с Z-буфером не сильно медленнее, чем без него?

Цитата:

Сообщение от undefined (Сообщение 808639)
именно поэтому не надо писать растеризатор на интерпретируемом языке, лучше использовать растеризатор встроенный в этот язык.

Но так как встроенного нет, говорить можно только о написании собственного.

undefined 26.03.2009 10:20

Цитата:

Ну раз я про это пишу, то взял с собственного опыта, наверное? Будете утверждать, что растеризация с Z-буфером не сильно медленнее, чем без него?
я всего лишь говорю что на приемлемых разрешениях аппаратная поддержка для z-буфер не требуется

Цитата:

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


Часовой пояс GMT +4, время: 04:08.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.