PSPx форум

PSPx форум (https://www.pspx.ru/forum/index.php)
-   Программирование для PSP (https://www.pspx.ru/forum/forumdisplay.php?f=101)
-   -   Софтверный 2.5D движок для PSP (https://www.pspx.ru/forum/showthread.php?t=106903)

Ilsor 17.06.2017 22:15

Софтверный 2.5D движок для PSP
 
Вот полные исходники моего софтверного 2.5D движка для PSP. Это тот же самый движок, что и тут (это моя статья). Просто я его перенёс на PSP и решил его выложить, пока PSP окончательно не стала никому не нужна. К сожалению, работает не быстро. Но работает. :)

Вот ссылка на движок.

Yoti 17.06.2017 23:22

Какие люди!:shok::drinks::good:

Ilsor 18.06.2017 07:52

:) Да вот, вспомнил про PSP и перенёс движок. А то он у меня и для Windows и для QNX, и для MS-DOS есть, а для PSP-нет. :) Придумать бы, как его ускорить - впрочем, можно разрядность цвета понизить. И ещё при перемещениях очень хорошо видны смазывания цветов. Интересно, неужели экран такой инерционный? Вроде бы в играх я такого не замечал (хотя в DOOM вроде бы я такое уже видел).

Yoti 18.06.2017 12:32

Ilsor,
многие тяжёлые игры работают в 16 битах (мало VRAM).
Что меня очень печалит, когда я смотрю на чёрный цвет.
И экран действительно достаточно инерционный (Pong).

Ilsor 18.06.2017 19:20

Это забавно, но я сегодня был на Юноне (это в СПб). Много лет я там бывал, но вот именно сегодня попались и Спектрум в красивом оформлении за 1500 и PSP Street.за 1000. А первой я увидел PSP и её и купил из интереса. Будет у меня две PSP. :) А спектрум уже не купил - мне на вокзал нужно было встречать и лишний груз ни к чему. А жаль. Вот такой облом. :) А раньше ничего такого не попадалось много лет. :) Ну, кроме МК-85. :)
Жаль, прошивка только виртуальная бывает к ней... :( И экран ооооочень инерционный. :( Но работает. Будет запасной.

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

Yoti 19.06.2017 13:12

Цитата:

Сообщение от Ilsor (Сообщение 1116494)
я сегодня был на Юноне

Бывал как-то раз.
Цитата:

Сообщение от Ilsor (Сообщение 1116494)
Спектрум в красивом оформлении

Никогда не было.
Цитата:

Сообщение от Ilsor (Сообщение 1116494)
и PSP Street

Этого добра навалом.
Цитата:

Сообщение от Ilsor (Сообщение 1116494)
Жаль, прошивка только виртуальная бывает к ней...

Пять секунд на активацию, я считаю, ерунда.

Ilsor 19.06.2017 19:59

Цитата:

Пять секунд на активацию, я считаю, ерунда.
Так-то оно так, но приятно, когда через 30 лет включил и работает (будем считать, что флэшка не сотрётся :) ), а не вспоминать, что там надо было сделать, чтобы всё заработало.

ErikPshat 20.06.2017 11:33

Цитата:

Сообщение от Yoti (Сообщение 1116481)
Ilsor,
И экран действительно достаточно инерционный (Pong).

Ага, только посмотреть на эту инерционность не судьба, ни одна ссылка не работает.
Ага, нашёл.

Yoti 20.06.2017 12:06

ErikPshat,
у меня в архивах тоже всё есть. Нужно только тему поправить.

ErikPshat 20.06.2017 14:19

Цитата:

Сообщение от Yoti (Сообщение 1116571)
Нужно только тему поправить.

Ну я уже поправил: https://www.pspx.ru/forum/showthread.php?t=71030

Ilsor 20.06.2017 19:11

Цитата:

Ну я уже поправил:
:cool2: Там ещё в самом конце осталась утиная охота. Её тоже можно в первое сообщение засунуть.
Правда, я не уверен, что в PSP ещё хоть кто-то играет. :)

ErikPshat 20.06.2017 19:25

Цитата:

Сообщение от Ilsor (Сообщение 1116586)
Там ещё в самом конце осталась утиная охота. Её тоже можно в первое сообщение засунуть.

А в первом сообщении предпоследнее разве не она?

Ilsor 20.06.2017 19:30

А, точно. Не заметил. :)

Понял, откуда шлейф. Вот из-за этой функции: sceDisplaySetFrameBuf((void*)VideoBuffer,512,PSP_DISPLAY_PIXEL_FORMAT_8888,0); Последний параметр у меня 1 был - синхронизация:
PSP_DISPLAY_SETBUF_IMMEDIATE Buffer change effective immediately. - это 0
PSP_DISPLAY_SETBUF_NEXTFRAME Buffer change effective next frame. - это 1

Честно говоря, я не заметил, что там такие значения и заданы через enum. Подумал, что либо есть, либо нет синхронизации. Вот как полезно бывает читать документацию. :) Но в архиве я не заменил на PSP_DISPLAY_SETBUF_IMMEDIATE - там остался 0. У себя-то я уже исправил на PSP_DISPLAY_SETBUF_IMMEDIATE вместо нуля, но не перезалил. :)

Он и синхронизирует. :) Я ещё кое-что изменил в движке - в физической части. Сейчас FPS стабильный при движении. Но, правда, только 20-30 FPS выдаёт в полноэкранном режиме 480x272. Но на 320x240 около 30-40. Архив в первом сообщении перезалит. :)

Ilsor 23.06.2017 19:16

Попытался задействовать графический ускоритель PSP для вывода картинки движка. Занятно. Едва координаты точки треугольника оказываются за спиной (координата Z больше либо равна нулю), как ускоритель просто выбрасывает весь выводимый треугольник! Это что ещё за шутки такие? Никогда тот же OpenGL так не делал - это задача ускорителя перенести точки на переднюю плоскость отсечения. И он это делает даже на PSP когда координата Z отрицательна! Открыл исходники Quake 1 для PSP. Вижу там целый модуль clipping.h - не знаю, из оригинального он Quake или нет, но похоже он как раз и занимается отрезанием частей полигонов, находящихся за спиной. Я правильно понимаю, что GU не умеет работать с положительными Z координатами точек?
И ещё я нифига не понял, что это такое: sceGumUpdateMatrix(); - я наивно полагал, что матрица задействуется сразу же после её задания. И оно так и было, пока я не начал менять матрицы каждый кадр в цикле (менял плоскость отсечения). Что за бред?
С текстурами такая же фигня - без sceKernelDcacheWritebackAll(); на текстурах артефакты - полоски и точки. Что за странный GU у PSP? Ему постоянно нужно сбрасывать кэш при смене текстур и просить пересчитать матрицы? Зачем же всё это нужно?

Ilsor 27.06.2017 13:38

Сделал отсечение по Z. А вот и не помогло. У GU проблема вовсе не в Z. У него какая-то проблема с проецированием - если точки куда-то попадают про проецировании, то они выбрасываются вместе с выводимым полигоном. Но вот какое это условие - я не знаю. Можно, правда, из матрицы проецирования найти все ограничивающие вид плоскости и отсечь по ним. Тогда, наверное, заработает.

Ilsor 29.06.2017 13:13

Вложений: 1
Всё, заработало. Разобрался с тем, что делают в Quake-1. Фишка вот какая - GU нужно чтобы вершины после проекции попадали в видимое окно. Иными словами, нужно отсечь вершины полигонов по плоскостям, ограничивающим вид игрока слева, справа, снизу и сверху. А передняя плоскость отсечётся автоматом. :)

Как это сделать? Считать три матрицы - GU_PROJECTION, GU_MODEL, GU_VIEW. Перемножить их и получить итоговую матрицу преобразования координат. Из этой матрицы можно вытащить все нужные ограничивающие вид плоскости (4 компоненты полученного вектора задают плоскость с уравнением ax+by+cz+w=0). (a,b,c) - вектор нормали, а w=a*x0+b*y0+c*z0 - характеризует некую точку (x0,y0,z0) плоскости. Сами координаты точки нам не нужны - достаточно знать w.
Вычисляется это всё так:

Функции для перевода вектора в нормализованное представление (x,y,z,w) и умножения матрицы на матрицу:

Код:

//----------------------------------------------------------------------------------------------------
//умножение двух матриц типа ScePspFMatrix4
//----------------------------------------------------------------------------------------------------
void CMain::MultiplyScePspFMatrix4(const ScePspFMatrix4& a,const ScePspFMatrix4& b,ScePspFMatrix4& out)
{
 out.x.x=a.x.x*b.x.x+a.x.y*b.y.x+a.x.z*b.z.x+a.x.w*b.w.x;
 out.x.y=a.x.x*b.x.y+a.x.y*b.y.y+a.x.z*b.z.y+a.x.w*b.w.y;
 out.x.z=a.x.x*b.x.z+a.x.y*b.y.z+a.x.z*b.z.z+a.x.w*b.w.z;
 out.x.w=a.x.x*b.x.w+a.x.y*b.y.w+a.x.z*b.z.w+a.x.w*b.w.w;

 out.y.x=a.y.x*b.x.x+a.y.y*b.y.x+a.y.z*b.z.x+a.y.w*b.w.x;
 out.y.y=a.y.x*b.x.y+a.y.y*b.y.y+a.y.z*b.z.y+a.y.w*b.w.y;
 out.y.z=a.y.x*b.x.z+a.y.y*b.y.z+a.y.z*b.z.z+a.y.w*b.w.z;
 out.y.w=a.y.x*b.x.w+a.y.y*b.y.w+a.y.z*b.z.w+a.y.w*b.w.w;

 out.z.x=a.z.x*b.x.x+a.z.y*b.y.x+a.z.z*b.z.x+a.z.w*b.w.x;
 out.z.y=a.z.x*b.x.y+a.z.y*b.y.y+a.z.z*b.z.y+a.z.w*b.w.y;
 out.z.z=a.z.x*b.x.z+a.z.y*b.y.z+a.z.z*b.z.z+a.z.w*b.w.z;
 out.z.w=a.z.x*b.x.w+a.z.y*b.y.w+a.z.z*b.z.w+a.z.w*b.w.w;

 out.w.x=a.w.x*b.x.x+a.w.y*b.y.x+a.w.z*b.z.x+a.w.w*b.w.x;
 out.w.y=a.w.x*b.x.y+a.w.y*b.y.y+a.w.z*b.z.y+a.w.w*b.w.y;
 out.w.z=a.w.x*b.x.z+a.w.y*b.y.z+a.w.z*b.z.z+a.w.w*b.w.z;
 out.w.w=a.w.x*b.x.w+a.w.y*b.y.w+a.w.z*b.z.w+a.w.w*b.w.w;
}

//----------------------------------------------------------------------------------------------------
//нормирование вектора типа ScePspFMatrix4
//----------------------------------------------------------------------------------------------------
void CMain::NormaliseScePspFVector4(ScePspFVector4& v)
{
 const float norma=sqrtf(v.x*v.x+v.y*v.y+v.z*v.z);
 const float scale=1.0f/norma;
 v.x*=scale;
 v.y*=scale;
 v.z*=scale;
 v.w*=scale;
}

Код:

  //получаем матрицу проецирования
  sceGumMatrixMode(GU_PROJECTION);
  ScePspFMatrix4 projection_matrix;
  sceGumStoreMatrix(&projection_matrix);
  //получаем матрицу видового преобразования
  sceGumMatrixMode(GU_VIEW);
  ScePspFMatrix4 view_matrix;
  sceGumStoreMatrix(&view_matrix);
  //получаем матрицу моделирования
  sceGumMatrixMode(GU_MODEL);
  ScePspFMatrix4 model_matrix;
  sceGumStoreMatrix(&model_matrix);
  sceGuFinish();

  //вычисляем общую матрицу view-projection
  ScePspFMatrix4 projection_view_matrix;
  MultiplyScePspFMatrix4(view_matrix,projection_matrix,projection_view_matrix);
  //вычисляем общую матрицу view-projection-model
  ScePspFMatrix4 projection_view_model_matrix;
  MultiplyScePspFMatrix4(model_matrix,projection_view_matrix,projection_view_model_matrix);
  //вычисляем матрицу view-model
  ScePspFMatrix4 view_model_matrix;
  MultiplyScePspFMatrix4(model_matrix,view_matrix,view_model_matrix);
  //вычисляем четыре плоскости отсечения по проекции (верх, низ, лево, право)
  ScePspFVector4 frustum[4];//четверка чисел описывает плоскость: ax+by+cz+d=0
  //левая
  frustum[0].x=projection_view_model_matrix.x.w+projection_view_model_matrix.x.x;
  frustum[0].y=projection_view_model_matrix.y.w+projection_view_model_matrix.y.x;
  frustum[0].z=projection_view_model_matrix.z.w+projection_view_model_matrix.z.x;
  frustum[0].w=projection_view_model_matrix.w.w+projection_view_model_matrix.w.x;
  NormaliseScePspFVector4(frustum[0]);
  //правая
  frustum[1].x=projection_view_model_matrix.x.w-projection_view_model_matrix.x.x;
  frustum[1].y=projection_view_model_matrix.y.w-projection_view_model_matrix.y.x;
  frustum[1].z=projection_view_model_matrix.z.w-projection_view_model_matrix.z.x;
  frustum[1].w=projection_view_model_matrix.w.w-projection_view_model_matrix.w.x;
  NormaliseScePspFVector4(frustum[1]);
  //верхняя
  frustum[2].x=projection_view_model_matrix.x.w-projection_view_model_matrix.x.y;
  frustum[2].y=projection_view_model_matrix.y.w-projection_view_model_matrix.y.y;
  frustum[2].z=projection_view_model_matrix.z.w-projection_view_model_matrix.z.y;
  frustum[2].w=projection_view_model_matrix.w.w-projection_view_model_matrix.w.y;
  NormaliseScePspFVector4(frustum[2]);
  //нижняя
  frustum[3].x=projection_view_model_matrix.x.w+projection_view_model_matrix.x.y;
  frustum[3].y=projection_view_model_matrix.y.w+projection_view_model_matrix.y.y;
  frustum[3].z=projection_view_model_matrix.z.w+projection_view_model_matrix.z.y;
  frustum[3].w=projection_view_model_matrix.w.w+projection_view_model_matrix.w.y;
  NormaliseScePspFVector4(frustum[3]);

Теперь у нас в массиве векторов frustum заданы плоскости отсечения.
А дальше надо просто найти пересечения сторон полигона с плоскостями и посчитать новые точки, а старые (которые вне плоскостей) выкинуть. Это делается так:

Код:

//----------------------------------------------------------------------------------------------------
//получить точку пересечения прямой и плоскости
//----------------------------------------------------------------------------------------------------
void CMain::GetIntersectionPlaneAndLine(const SGuNVCTPoint& A,const SGuNVCTPoint& B,SGuNVCTPoint& new_point,float nx,float ny,float nz,float w)
{
 new_point=A;
 float ax=A.sGuVertex.X;
 float ay=A.sGuVertex.Y;
 float az=A.sGuVertex.Z;
 float au=A.sGuTexture.U;
 float av=A.sGuTexture.V;

 float bx=B.sGuVertex.X;
 float by=B.sGuVertex.Y;
 float bz=B.sGuVertex.Z;
 float bu=B.sGuTexture.U;
 float bv=B.sGuTexture.V;

 float dx=bx-ax;
 float dy=by-ay;
 float dz=bz-az;
 float du=bu-au;
 float dv=bv-av;

 float top=(nx*ax)+(ny*ay)+(nz*az)+w;
 float bottom=(nx*dx)+(ny*dy)+(nz*dz);
 float time=-top/bottom;

 float vx=ax+time*dx;
 float vy=ay+time*dy;
 float vz=az+time*dz;
 float vu=au+time*du;
 float vv=av+time*dv;
 //добавляем новую точку
 SetVertexCoord(new_point.sGuVertex,vx,vy,vz);
 SetTextureCoord(new_point.sGuTexture,vu,vv);
}
//----------------------------------------------------------------------------------------------------
//выполнить коррекцию координат
//----------------------------------------------------------------------------------------------------
void CMain::Clip(const vector<SGuNVCTPoint>& vector_point_input,vector<SGuNVCTPoint>& vector_point_output,float nx,float ny,float nz,float w)
{
 vector_point_output.clear();
 long point=vector_point_input.size();
 for(long n=0;n<point;n++)
 {
  long next_p=n+1;
  if (next_p>=point) next_p-=point;

  const SGuNVCTPoint *sGuNVCTPoint_Current_Ptr=&(vector_point_input[n]);
  float current_vx=sGuNVCTPoint_Current_Ptr->sGuVertex.X;
  float current_vy=sGuNVCTPoint_Current_Ptr->sGuVertex.Y;
  float current_vz=sGuNVCTPoint_Current_Ptr->sGuVertex.Z;
  //определяем положение относительно плоскости отсечения
  float current_ret=current_vx*nx+current_vy*ny+current_vz*nz+w;

  const SGuNVCTPoint *sGuNVCTPoint_Next_Ptr=&(vector_point_input[next_p]);
  float next_vx=sGuNVCTPoint_Next_Ptr->sGuVertex.X;
  float next_vy=sGuNVCTPoint_Next_Ptr->sGuVertex.Y;
  float next_vz=sGuNVCTPoint_Next_Ptr->sGuVertex.Z;
  //определяем положение относительно плоскости отсечения
  float next_ret=next_vx*nx+next_vy*ny+next_vz*nz+w;

  if (current_ret>0)//текущая точка видима
  {
  if (next_ret>0)//следующая точка видима
  {
    vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr);
  }
  else
  {
    //добавляем новую точку пересечения
    SGuNVCTPoint sGuNVCTPoint_New;
    GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w);
    vector_point_output.push_back(sGuNVCTPoint_New);
  }
  }
  else//текущая точка не видна
  {
  if (next_ret>0)//следующая точка видна
  {
    //добавляем новую точку пересечения
    SGuNVCTPoint sGuNVCTPoint_New;
    GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w);
    vector_point_output.push_back(sGuNVCTPoint_New);
    //добавляем сдудующую точку
    vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr);
  }
  }
 }
}

Тогда рисовать можно вот так:

Код:

//#pragma pack(1)
//[for vertices(1-8)] [weights (0-8)] [texture uv] [color] [normal] [vertex] [/for]

#pragma pack(1)
struct SGuVertex
{
 float X;
 float Y;
 float Z;
};
struct SGuNormal
{
 float Nx;
 float Ny;
 float Nz;
};
struct SGuTexture
{
 float U;
 float V;
};
struct SGuColor
{
 unsigned long Color;
};
#pragma pack()

#pragma pack(32)
struct SGuNVCTPoint
{
 SGuTexture sGuTexture;
 SGuColor sGuColor;
 SGuNormal sGuNormal;
 SGuVertex sGuVertex;
};
#pragma pack()

Код:

  //задаём геометрию
  SGuNVCTPoint sGuNVCTPoint;
  vector<SGuNVCTPoint> vector_point;

  SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,100,0);
  SetTextureCoord(sGuNVCTPoint.sGuTexture,0,0);
  SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1);
  SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF);
  vector_point.push_back(sGuNVCTPoint);

  SetVertexCoord(sGuNVCTPoint.sGuVertex,100,100,0);
  SetTextureCoord(sGuNVCTPoint.sGuTexture,1,0);
  SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1);
  SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF);
  vector_point.push_back(sGuNVCTPoint);

  SetVertexCoord(sGuNVCTPoint.sGuVertex,100,-100,0);
  SetTextureCoord(sGuNVCTPoint.sGuTexture,1,1);
  SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1);
  SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF);
  vector_point.push_back(sGuNVCTPoint);

  SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,-100,0);
  SetTextureCoord(sGuNVCTPoint.sGuTexture,0,1);
  SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1);
  SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF);
  vector_point.push_back(sGuNVCTPoint);
  //выполняем отсечение
  vector<SGuNVCTPoint> vector_clip_point;
  for(long n=0;n<4;n++)
  {
  float nx=frustum[n].x;
  float ny=frustum[n].y;
  float nz=frustum[n].z;
  float w=frustum[n].w;

  Clip(vector_point,vector_clip_point,nx,ny,nz,w);
  vector_point=vector_clip_point;
  }

  //теперь рисуем
  sceGuStart(GU_DIRECT,DisplayList);
  //выводим прямоугольник
  sceGuColor(0xffffffff);
  //вершина с нормалью, текстурой, цветом и координатами
  sceGuEnable(GU_TEXTURE_2D);
  sceGuTexMode(GU_PSM_8888,0,0,0);
  sceGuTexImage(0,WidthImage,HeightImage,WidthImage,Data);
  sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA);
  sceGuTexFilter(GU_NEAREST,GU_NEAREST);
  sceGuTexWrap(GU_REPEAT,GU_REPEAT);
  sceGuTexScale(1,1);
  sceGuTexOffset(0,0);

  long vertex_amount=vector_point.size();

  SGuNVCTPoint *sGuNVCTPoint_Ptr=(SGuNVCTPoint*)sceGuGetMemory(vertex_amount*sizeof(SGuNVCTPoint));
  if (sGuNVCTPoint_Ptr!=NULL)
  {
  for(long n=0;n<vertex_amount;n++) sGuNVCTPoint_Ptr[n]=vector_point[n];
  sceGumDrawArray(GU_TRIANGLE_FAN,GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D|GU_NORMAL_32BITF|GU_TEXTURE_32BITF,vertex_amount,0,sGuNVCTPoint_Ptr);
  }

  sceGuDisable(GU_TEXTURE_2D);
  //запускаем список на выполнение
  sceGuFinish();
  sceGuSync(GU_SYNC_WAIT,GU_SYNC_FINISH);

Можно, кстати, векторный процессор PSP использовать для скалярного умножения векторов:

Код:

//выполняем отсечение
 vector<SGuNVCTPoint> vector_clip_point;
 //используем векторный процессор PSP
 __asm__ volatile
 (
  "ulv.q        C700, %0\n"        //загружаем вектор в регистр
  "ulv.q        C710, %1\n"        //загружаем вектор в регистр
  "ulv.q        C720, %2\n"        //загружаем вектор в регистр
  "ulv.q        C730, %3\n"        //загружаем вектор в регистр
  :: "m"(FrustumPlane[0]),"m"(FrustumPlane[1]),"m"(FrustumPlane[2]),"m"(FrustumPlane[3])
 );
 //проверим необходимость отсечения
 long vertex=vector_point.size();
 bool clipping=false;
 for(long n=0;n<vertex;n++)
 {
  ScePspFVector4 current_vertex;
  current_vertex.x=vector_point[n].sGuVertex.X;
  current_vertex.y=vector_point[n].sGuVertex.Y;
  current_vertex.z=vector_point[n].sGuVertex.Z;
  current_vertex.w=1;
  float ret1,ret2,ret3,ret4;
  __asm__ volatile
  (
  "ulv.q        C610, %4\n"                        // загружаем вектор вершины в регистр
  "vone.s        S613\n"                                // Now set the 4th entry to be 1 as that is just random
  "vdot.q        S620, C700, C610\n"        // s620 = вычисляем скалярное произведение
  "vdot.q        S621, C710, C610\n"        // s621 = вычисляем скалярное произведение
  "vdot.q        S622, C720, C610\n"        // s622 = вычисляем скалярное произведение
  "vdot.q        S623, C730, C610\n"        // s623 = вычисляем скалярное произведение
  "mfv        %0, S620\n"                        // out1 = s620
  "mfv        %1, S621\n"                        // out2 = s621
  "mfv        %2, S622\n"                        // out3 = s622
  "mfv        %3, S623\n"                        // out4 = s623
  : "=r"(ret1), "=r"(ret2), "=r"(ret3), "=r"(ret4) : "m"(current_vertex)
  );
  if (ret1<0 || ret2<0 || ret3<0 || ret4<0)//требуется отсечение
  {
  clipping=true;
  break;
  }
 }

Но эта функция из движка, а не из приводимой ниже программы. Взял я этот код процессора из того же Quake-1.
Движок под GU тоже заработал. Только нифига ускорения не вышло - тормоза одни. Причём, при отключённом текстурировании скорость резко возрастает. Может, нужно как-то текстуру в видеопамять перебросить.

Вот сама демонстрационная программа (не забудьте скопировать текстуру в каталог с eboot.pbp):

Ilsor 30.06.2017 22:04

Кстати, если текстуры поместить в видеопамяти (которая получается по sceGeEdramGetAddr()), то скорость текстурирования резко возрастает. Вот только на все текстуры памяти не хватает. :) Придётся в видеопамяти кэшировать только те текстуры, которые в данный момент используются при выводе графики.

Ilsor 05.07.2017 21:18

Вот ссылка на движок под GU с форматом цвета 565 - 16 бит. Этому движку нужны файлы из движка выше - текстуры и карта. Кстати, в той карте есть ошибочно нарисованный сегмент (он наложился поверх другого) в месте, где водопады. Из-за этого там будут глюки с текстурой - будет видно наложение.


Текущее время: 02:05. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2025, vBulletin Solutions, Inc. Перевод: zCarot
PSPx Forum - Сообщество фанатов игровых консолей.